firewire: cdev: prevent race between first get_info ioctl
commitc20974dfa539046b0cec0af14a2d707c39f33b2a
authorStefan Richter <stefanr@s5r6.in-berlin.de>
Sat, 9 Jul 2011 14:43:22 +0000 (9 16:43 +0200)
committerAndi Kleen <ak@linux.intel.com>
Mon, 1 Aug 2011 20:55:01 +0000 (1 13:55 -0700)
treeef8884546e520a6ffb30570a913ea349e4a83c5e
parent5464598561256330d2a14d9616921deb97b69103
firewire: cdev: prevent race between first get_info ioctl

[ upstream commit 93b37905f70083d6143f5f4dba0a45cc64379a62 ]
 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>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
drivers/firewire/core-cdev.c
include/linux/firewire-cdev.h