In an embedded system running Linux, we have a PCI driver in user-space making use of the kernel driver for UIO. The application can trigger registration of the device which calls
__uio_register_device() in the kernel's
uio.c. Then the application opens the device file (
/dev/uio0). And then it misbehaves by unregistering the device (
uio_unregister_device()) which frees some kernel memory holding device information. Then the application closes the file - and the kernel panics because pointers which have been freed are being accessed.
Apart from fixing the application, how can I make the Linux kernel robust against this?
uio_release() get file pointers which point to the critical allocated memory (in
uio_unregister_device() doesn't have this information, so I don't know what to do. Or is there a way to force-close the file in the application? Any other suggestions or a different interpretation of what's happening?
Edit: can be easily reproduced as follows - and shows the user-space perspective:
# replace '1234 abcd' by vendor id and device id echo '1234 abcd' > /sys/bus/pci/drivers/uio_pci_generic/new_id echo '0000:00:01.0' > /sys/bus/pci/drivers/uio_pci_generic/bind # 'bind' may not even be needed. /dev/uio0 is created cat /dev/uio0 & # now be bad echo '0000:00:01.0' > /sys/bus/pci/drivers/uio_pci_generic/unbind kill <cat process ID> # kernel panic...
Causes a crash due to
Unable to handle kernel paging request at virtual address - with three different flavors. Either
idev->owner is an invalid pointer (not necessary NULL, just random data).