summaryrefslogtreecommitdiffstats
path: root/include/linux/firewire-cdev.h
diff options
context:
space:
mode:
authorStefan Richter2011-07-09 16:43:22 +0200
committerStefan Richter2011-07-16 07:24:32 +0200
commit93b37905f70083d6143f5f4dba0a45cc64379a62 (patch)
treeb6917581cd390ed9967e1df9922940362ad4309e /include/linux/firewire-cdev.h
parentfirewire: cdev: return -ENOTTY for unimplemented ioctls, not -EINVAL (diff)
downloadkernel-qcow2-linux-93b37905f70083d6143f5f4dba0a45cc64379a62.tar.gz
kernel-qcow2-linux-93b37905f70083d6143f5f4dba0a45cc64379a62.tar.xz
kernel-qcow2-linux-93b37905f70083d6143f5f4dba0a45cc64379a62.zip
firewire: cdev: prevent race between first get_info ioctl and bus reset event queuing
Between open(2) of a /dev/fw* and the first FW_CDEV_IOC_GET_INFO ioctl(2) on it, the kernel already queues FW_CDEV_EVENT_BUS_RESET events to be read(2) by the client. The get_info ioctl is practically always issued right away after open, hence this condition only occurs if the client opens during a bus reset, especially during a rapid series of bus resets. The problem with this condition is twofold: - These bus reset events carry the (as yet undocumented) @closure value of 0. But it is not the kernel's place to choose closures; they are privat to the client. E.g., this 0 value forced from the kernel makes it unsafe for clients to dereference it as a pointer to a closure object without NULL pointer check. - It is impossible for clients to determine the relative order of bus reset events from get_info ioctl(2) versus those from read(2), except in one way: By comparison of closure values. Again, such a procedure imposes complexity on clients and reduces freedom in use of the bus reset closure. So, change the ABI to suppress queuing of bus reset events before the first FW_CDEV_IOC_GET_INFO ioctl was issued by the client. Note, this ABI change cannot be version-controlled. The kernel cannot distinguish old from new clients before the first FW_CDEV_IOC_GET_INFO ioctl. We will try to back-merge this change into currently maintained stable/ longterm series, and we only document the new behaviour. The old behavior is now considered a kernel bug, which it basically is. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Cc: <stable@kernel.org>
Diffstat (limited to 'include/linux/firewire-cdev.h')
-rw-r--r--include/linux/firewire-cdev.h3
1 files changed, 3 insertions, 0 deletions
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index 4ff09889c5c0..55814aa33be2 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -475,6 +475,9 @@ union fw_cdev_event {
* of the bus. This does not cause a bus reset to happen.
* @bus_reset_closure: Value of &closure in this and subsequent bus reset events
* @card: The index of the card this device belongs to
+ *
+ * As a side effect, reception of %FW_CDEV_EVENT_BUS_RESET events to be read(2)
+ * is started by this ioctl.
*/
struct fw_cdev_get_info {
__u32 version;