Hi, I'd like to report two security issues in the Linux kernel's floppy disk driver (yes, really). The issue is present in mainline versions and, from some quick archaeology, appears to go back to Linux 1.3.34 (ie. see and its mention of floppy driver changes). The first issue lies in the driver's processing of FDRAWCMD ioctls, specifically in its handling of copying floppy_raw_cmd ioctl argument structures from and to userspace. There are four relevant functions in drivers/block/floppy.c: raw_cmd_{ioctl,copyin,copyout,free}. First, raw_cmd_ioctl calls raw_cmd_copyin. This function kmallocs space for a floppy_raw_cmd structure and stores the resulting allocation in the "rcmd" pointer argument. It then attempts to copy_from_user the structure from userspace. If this fails, an early EFAULT return is taken. The problem is that even if the early return is taken, the pointer to the non-/partially-initialized floppy_raw_cmd structure has already been returned via the "rcmd" pointer. Back out in raw_cmd_ioctl, it attempts to raw_cmd_free this pointer. raw_cmd_free attempts to free any DMA pages allocated for the raw command, kfrees the raw command structure itself, and follows the linked list, if any, of further raw commands (a user can specify the FD_RAW_MORE flag to signal that there are more raw commands to follow in a single FDRAWCMD ioctl). So, a malicious user can send a FDRAWCMD ioctl with a raw command argument structure that has some bytes inaccessible (ie. off the end of an allocated page). The copy_from_user will fail but raw_cmd_free will attempt to process the floppy_raw_cmd as if it had been fully initialized by the rest of raw_cmd_copyin. The user can control the arguments passed to fd_dma_mem_free and kfree (by making use of the linked-list feature and specifying the target address as a next-in-list structure). There is also another issue which greatly helps in the exploitation of this other issue. In raw_cmd_copyout, the entire floppy_raw_cmd structure is copy_to_user'd back to userspace after raw command processing. The issue is that the entire structure is copied back, which leaks to userspace the address of the allocated DMA pages, if any, and the address of the next-in-list command structure, if any. A malicious user can send a FDRAWCMD ioctl with the FD_RAW_MORE flag set and, upon inspecting the result in the command argument, find the address of the last floppy_raw_cmd allocation on the kmalloc-nnn slab. By combining these two issues, one can perform the following attack: * Find the address of the next kmalloc-nnn allocation * Allocate a target object at that location by invoking a suitable kernel service * Free that target object by causing raw_cmd_free to kfree a user-controlled linked-list next pointer * Overwrite the target object's remains with ie. another floppy_raw_cmd structure * Invoke a payload by getting the kernel to callback a function pointer that is now controlled by the user via the overwritten target object. Ie., the vulnerabilities are a kfree() of any desired object, and the leak of the address of a temporary kmalloc() allocation. Needless to say, these two primitives work together nicely to form a stable method of exploitation. I do have a POC exploit written up, but the code is very hacky; it is missing a more tidy method of symbol resolution and more customizable structure-offset control. However, I've attached it to this mail. mattd@ps840:~$ ls -l fd -rwxr-xr-x 1 mattd mattd 13364 Apr 27 12:38 fd mattd@ps840:~$ id uid=1000(mattd) gid=1000(mattd) groups=1000(mattd),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),64040(grsec-tpe) mattd@ps840:~$ ~/fd commit_creds = 0xffffffff81081460 prepare_kernel_cred = 0xffffffff81081710 cmd2[0].next = 0xffff8800abf8e740 root@ps840:~# id uid=0(root) gid=0(root) groups=0(root) root@ps840:~# exit mattd@ps840:~$ id uid=1000(mattd) gid=1000(mattd) groups=1000(mattd),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),64040(grsec-tpe) mattd@ps840:~$ This exploit uses seq_file structures as the target object in the kmalloc-128 slab; it has an ops-style pointer to an array of function pointer callbacks. It's allocated upon opening a suitable kernel-generated file, such as /proc/{kallsyms,modules,sched_debug}. After getting ring0 access, the exploit fiddles with the struct file containing the now-freed seq_file (as its private_data) so as to increment its f_count so it will never attempt to be released again. I'm happy with whatever timeline is decided upon for disclosure, this is the first notification of the issues, I have not requested a CVE, and am happy to be credited. Thanks for your attention! Please let me know if anything need to be clarified. - Matthew Daley