From 551f4cb9de716ffcdaf968c99a450c22ff12e8c3 Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Fri, 16 May 2008 11:15:23 -0400 Subject: [PATCH] firewire: prevent userspace from accessing shut down devices If userspace ignores the POLLERR bit from poll(), and only attempts to read() the device when POLLIN is set, it can still make ioctl() calls on a device that has been removed from the system. The node_id and generation returned by GET_INFO will be outdated, but INITIATE_BUS_RESET would still cause a bus reset, and GET_CYCLE_TIMER will return data. And if you guess the correct generation to use, you can send requests to a different device on the bus, and get responses back. This patch prevents open, ioctl, compat_ioctl, and mmap against shutdown devices. Signed-off-by: Jay Fenlason Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 4a541921a14a..dda14015e873 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -113,6 +113,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file) if (device == NULL) return -ENODEV; + if (fw_device_is_shutdown(device)) { + fw_device_put(device); + return -ENODEV; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); if (client == NULL) { fw_device_put(device); @@ -901,6 +906,9 @@ fw_device_op_ioctl(struct file *file, { struct client *client = file->private_data; + if (fw_device_is_shutdown(client->device)) + return -ENODEV; + return dispatch_ioctl(client, cmd, (void __user *) arg); } @@ -911,6 +919,9 @@ fw_device_op_compat_ioctl(struct file *file, { struct client *client = file->private_data; + if (fw_device_is_shutdown(client->device)) + return -ENODEV; + return dispatch_ioctl(client, cmd, compat_ptr(arg)); } #endif @@ -922,6 +933,9 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) unsigned long size; int page_count, retval; + if (fw_device_is_shutdown(client->device)) + return -ENODEV; + /* FIXME: We could support multiple buffers, but we don't. */ if (client->buffer.pages != NULL) return -EBUSY;