• David Herrmann's avatar
    HID: Fix race condition between driver core and ll-driver · 4ea54542
    David Herrmann authored
    HID low level drivers register new devices with the HID core which then
    adds the devices to the HID bus. The HID bus normally immediately probes
    an appropriate driver which then handles HID input for this device.
    The ll driver now uses the hid_input_report() function to report input
    events for a specific device. However, if the HID bus unloads the driver
    at the same time (for instance via a call to
     /sys/bus/hid/devices/<dev>/unbind) then the hdev->driver pointer may be
    used by hid_input_report() and hid_device_remove() at the same time
    which may cause hdev->driver to point to invalid memory.
    
    This fix adds a semaphore to every hid device which protects
    hdev->driver from asynchronous access. This semaphore is locked during
    driver *_probe and *_remove and also inside hid_input_report(). The
    *_probe and *_remove functions may sleep so the semaphore is good here,
    however, hid_input_report() is in atomic context and hence only uses
    down_trylock(). If it cannot acquire the lock it simply drops the input
    package.
    
    The low-level drivers report input events synchronously so
    hid_input_report() should never be entered twice at the same time on the
    same device. Hence, the lock should always be available. But if the
    driver is currently probed/removed then the lock is not available and
    dropping the package should be safe because this is what would have
    happened if the package arrived some milliseconds earlier/later.
    
    This also fixes another race condition while probing drivers:
    First the *_probe function of the driver is called and only if that
    succeeds, the related input device of hidinput is registered. If the low
    level driver reports input events after the *_probe function returned
    but before the input device is registered, then a NULL pointer
    dereference will occur. (Equivalently on driver remove function).
    This is not possible anymore, since the semaphore lock drops all
    incoming packages until the driver/device is fully initialized.
    Signed-off-by: default avatarDavid Herrmann <dh.herrmann@googlemail.com>
    Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
    4ea54542
hid-core.c 71.2 KB