Skip to content

Commit 4ab3a08

Browse files
pietroborrellobentiss
authored andcommitted
HID: asus: use spinlock to safely schedule workers
Use spinlocks to deal with workers introducing a wrapper asus_schedule_work(), and several spinlock checks. Otherwise, asus_kbd_backlight_set() may schedule led->work after the structure has been freed, causing a use-after-free. Fixes: af22a61 ("HID: asus: support backlight on USB keyboards") Signed-off-by: Pietro Borrello <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent 315c537 commit 4ab3a08

File tree

1 file changed

+11
-4
lines changed

1 file changed

+11
-4
lines changed

drivers/hid/hid-asus.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,16 @@ static int rog_nkey_led_init(struct hid_device *hdev)
491491
return ret;
492492
}
493493

494+
static void asus_schedule_work(struct asus_kbd_leds *led)
495+
{
496+
unsigned long flags;
497+
498+
spin_lock_irqsave(&led->lock, flags);
499+
if (!led->removed)
500+
schedule_work(&led->work);
501+
spin_unlock_irqrestore(&led->lock, flags);
502+
}
503+
494504
static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
495505
enum led_brightness brightness)
496506
{
@@ -502,7 +512,7 @@ static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
502512
led->brightness = brightness;
503513
spin_unlock_irqrestore(&led->lock, flags);
504514

505-
schedule_work(&led->work);
515+
asus_schedule_work(led);
506516
}
507517

508518
static enum led_brightness asus_kbd_backlight_get(struct led_classdev *led_cdev)
@@ -526,9 +536,6 @@ static void asus_kbd_backlight_work(struct work_struct *work)
526536
int ret;
527537
unsigned long flags;
528538

529-
if (led->removed)
530-
return;
531-
532539
spin_lock_irqsave(&led->lock, flags);
533540
buf[4] = led->brightness;
534541
spin_unlock_irqrestore(&led->lock, flags);

0 commit comments

Comments
 (0)