CVE-2008-5079: Linux ATM Local DoS

This vulnerability was found by Hugo Dias on 14 November 2008 and publicly disclosed on 5 December 2008 as you can see here. This ATM vulnerability affects Linux kernel up to 2.6.27.8 release and the bug can be found at net/atm/svc.c. Here is the code taken from Linux kernel 2.6.27.8 release. For those of you that don’t now what SVC sockets are, they are just common sockets for ATM networks that are Switched Virtual Circuit architecture (if you don’t know either what this is, then maybe you should read your A. Tanenbaum’s Computer Networks copy again). Here is the vulnerable function:

281
282 static int svc_listen(struct socket *sock,int backlog)
283 {

This function can be reached through listen(2) system call when managing ATM SVC sockets. Now, if we continue with this function, we are going to see this:

Nothing notable apart from the call to vcc_insert_socket() which is used to insert the socket descriptor to the VCC and can be found at net/atm/common.c. Have a look at line 292. You can see that VCC’s (Virtual Channel Connection) flags of the ATM device are checked against P2MP session control descriptor but it is not checked against ATM_VF_LISTEN which is used to mark a socket if it’s used for listening. This means that we can have more than one descriptors liten(2)ing on the same ATM SVC socket. This was bug was fixed simply by adding this:

This by itself might seem harmless but as H. Dias found, this will generate unassigned PVC (Private Virtual Circuit) and/or SVC (Switched Virtual Circuit) entries. These are accessible through /proc/net/atm/vc file, but as he pointed out when net/atm/proc.c tries to access these entries it enters an infinite loop. Here is how this is done:

Here you can see at line 92 that the for loop keeps iterating through the sockets until it reaches a NULL. Of course, because of the previous vulnerability on ATM SVC listen(2) we can make it access out of bounds entries which can only be stopped if compare_family() iterates enough times to make l a negative integer or if a NULL entry is reached. To reach this code we can view the contents of /proc/net/atm/vc. By doing this, we’re indirectly calling this function to provide us with a listing. Here is my extremely simple PoC for this vulnerability: