diff mbox series

[v2,10/37] HID: logitech-dj: protect the paired_dj_devices access in add_djhid_dev with the lock

Message ID 20190410145459.11430-11-hdegoede@redhat.com (mailing list archive)
State Superseded
Delegated to: Jiri Kosina
Headers show
Series HID: logitech: Handling of non DJ receivers in hid-logitech-dj | expand

Commit Message

Hans de Goede April 10, 2019, 2:54 p.m. UTC
This protects against logi_dj_recv_add_djhid_device, adding a device to
paired_dj_devices from the delayedwork callback, racing versus
logi_dj_raw_event trying to access that device.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/hid/hid-logitech-dj.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff mbox series

Patch

diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 32b985104a8e..49d34989fc10 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -393,12 +393,14 @@  static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
 	struct hid_device *dj_hiddev;
 	struct dj_device *dj_dev;
 	u8 device_index = workitem->device_index;
+	unsigned long flags;
 
 	/* Device index goes from 1 to 6, we need 3 bytes to store the
 	 * semicolon, the index, and a null terminator
 	 */
 	unsigned char tmpstr[3];
 
+	/* We are the only one ever adding a device, no need to lock */
 	if (djrcv_dev->paired_dj_devices[device_index]) {
 		/* The device is already known. No need to reallocate it. */
 		dbg_hid("%s: device is already known\n", __func__);
@@ -443,7 +445,9 @@  static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
 	dj_dev->device_index = device_index;
 	dj_hiddev->driver_data = dj_dev;
 
+	spin_lock_irqsave(&djrcv_dev->lock, flags);
 	djrcv_dev->paired_dj_devices[device_index] = dj_dev;
+	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
 
 	if (hid_add_device(dj_hiddev)) {
 		dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n",
@@ -454,7 +458,9 @@  static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
 	return;
 
 hid_add_device_fail:
+	spin_lock_irqsave(&djrcv_dev->lock, flags);
 	djrcv_dev->paired_dj_devices[device_index] = NULL;
+	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
 	kfree(dj_dev);
 dj_device_allocate_fail:
 	hid_destroy_device(dj_hiddev);