| From ee1ddc29bb8a281bcef0b1c53dc3853a661c51a9 Mon Sep 17 00:00:00 2001 |
| From: Hanno Zulla <kontakt@hanno.de> |
| Date: Tue, 18 Feb 2020 12:39:31 +0100 |
| Subject: [PATCH] HID: hid-bigbenff: fix race condition for scheduled work |
| during removal |
| |
| commit 4eb1b01de5b9d8596d6c103efcf1a15cfc1bedf7 upstream. |
| |
| It's possible that there is scheduled work left while the device is |
| already being removed, which can cause a kernel crash. Adding a flag |
| will avoid this. |
| |
| Signed-off-by: Hanno Zulla <kontakt@hanno.de> |
| Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/hid/hid-bigbenff.c b/drivers/hid/hid-bigbenff.c |
| index f8c552b64a89..db6da21ade06 100644 |
| --- a/drivers/hid/hid-bigbenff.c |
| +++ b/drivers/hid/hid-bigbenff.c |
| @@ -174,6 +174,7 @@ static __u8 pid0902_rdesc_fixed[] = { |
| struct bigben_device { |
| struct hid_device *hid; |
| struct hid_report *report; |
| + bool removed; |
| u8 led_state; /* LED1 = 1 .. LED4 = 8 */ |
| u8 right_motor_on; /* right motor off/on 0/1 */ |
| u8 left_motor_force; /* left motor force 0-255 */ |
| @@ -190,6 +191,9 @@ static void bigben_worker(struct work_struct *work) |
| struct bigben_device, worker); |
| struct hid_field *report_field = bigben->report->field[0]; |
| |
| + if (bigben->removed) |
| + return; |
| + |
| if (bigben->work_led) { |
| bigben->work_led = false; |
| report_field->value[0] = 0x01; /* 1 = led message */ |
| @@ -304,6 +308,7 @@ static void bigben_remove(struct hid_device *hid) |
| { |
| struct bigben_device *bigben = hid_get_drvdata(hid); |
| |
| + bigben->removed = true; |
| cancel_work_sync(&bigben->worker); |
| hid_hw_stop(hid); |
| } |
| @@ -324,6 +329,7 @@ static int bigben_probe(struct hid_device *hid, |
| return -ENOMEM; |
| hid_set_drvdata(hid, bigben); |
| bigben->hid = hid; |
| + bigben->removed = false; |
| |
| error = hid_parse(hid); |
| if (error) { |
| -- |
| 2.7.4 |
| |