VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46213

CVE-2026-46213

Description

In the Linux kernel, the following vulnerability has been resolved:

HID: appletb-kbd: fix UAF in inactivity-timer cleanup path

Commit 38224c472a03 ("HID: appletb-kbd: fix slab use-after-free bug in appletb_kbd_probe") added timer_delete_sync(&kbd->inactivity_timer) to both the probe close_hw error path and appletb_kbd_remove(), but the way it was wired in left the inactivity timer reachable during driver tear-down via two distinct windows.

Window A -- put_device() before timer_delete_sync():

put_device(&kbd->backlight_dev->dev); timer_delete_sync(&kbd->inactivity_timer);

The inactivity_timer softirq reads kbd->backlight_dev and calls backlight_device_set_brightness() -> mutex_lock(&ops_lock). If a concurrent hid_appletb_bl unbind drops the last devm reference between these two calls, the backlight_device is freed and the mutex_lock() touches freed memory.

Window B -- backlight cleanup before hid_hw_stop():

if (kbd->backlight_dev) { timer_delete_sync(...); put_device(...); } hid_hw_close(hdev); hid_hw_stop(hdev);

Even after Window A is closed, hid_hw_close()/hid_hw_stop() still run afterwards, so a late ".event" callback from the HID core (USB URB completion on real Apple hardware) can arrive after timer_delete_sync() drained the softirq but before put_device() drops the reference. That callback reaches reset_inactivity_timer(), which calls mod_timer() and re-arms the timer. The freshly re-armed timer can then fire on the about-to-be-freed backlight_device.

Both windows produce the same KASAN slab-use-after-free:

BUG: KASAN: slab-use-after-free in __mutex_lock+0x1aab/0x21c0 Read of size 8 at addr ffff88803ee9a108 by task swapper/0/0 Call Trace:

__mutex_lock backlight_device_set_brightness appletb_inactivity_timer call_timer_fn run_timer_softirq handle_softirqs Allocated by task N: devm_backlight_device_register appletb_bl_probe Freed by task M: (concurrent hid_appletb_bl unbind path)

Close both windows at once by reworking the tear-down in appletb_kbd_remove() and in the probe close_hw error path so that

1) hid_hw_close()/hid_hw_stop() run before the backlight cleanup, guaranteeing no further .event callback can fire and re-arm the timer, and 2) inside the "if (kbd->backlight_dev)" block, timer_delete_sync() runs before put_device(), so the softirq is drained before the final reference is dropped.

Affected products

2

Patches

6
59a79938ca55

HID: appletb-kbd: fix UAF in inactivity-timer cleanup path

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSangyun KimApr 20, 2026Fixed in 6.18.32via kernel-cna
1 file changed · +8 9
  • drivers/hid/hid-appletb-kbd.c+8 9 modified
    diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c
    index 0b10cff465e179..711403441e3089 100644
    --- a/drivers/hid/hid-appletb-kbd.c
    +++ b/drivers/hid/hid-appletb-kbd.c
    @@ -440,13 +440,13 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
     unregister_handler:
     	input_unregister_handler(&kbd->inp_handler);
     close_hw:
    -	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
    -		timer_delete_sync(&kbd->inactivity_timer);
    -	}
     	hid_hw_close(hdev);
     stop_hw:
     	hid_hw_stop(hdev);
    +	if (kbd->backlight_dev) {
    +		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
    +	}
     	return ret;
     }
     
    @@ -457,13 +457,13 @@ static void appletb_kbd_remove(struct hid_device *hdev)
     	appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
     
     	input_unregister_handler(&kbd->inp_handler);
    +	hid_hw_close(hdev);
    +	hid_hw_stop(hdev);
    +
     	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
     		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
     	}
    -
    -	hid_hw_close(hdev);
    -	hid_hw_stop(hdev);
     }
     
     #ifdef CONFIG_PM
    -- 
    cgit 1.3-korg
    
    
    
93d989e47bc3

HID: appletb-kbd: fix UAF in inactivity-timer cleanup path

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSangyun KimApr 20, 2026Fixed in 7.0.9via kernel-cna
1 file changed · +8 9
  • drivers/hid/hid-appletb-kbd.c+8 9 modified
    diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c
    index 0fdc0968b9ef26..8feac9e3589b83 100644
    --- a/drivers/hid/hid-appletb-kbd.c
    +++ b/drivers/hid/hid-appletb-kbd.c
    @@ -440,13 +440,13 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
     unregister_handler:
     	input_unregister_handler(&kbd->inp_handler);
     close_hw:
    -	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
    -		timer_delete_sync(&kbd->inactivity_timer);
    -	}
     	hid_hw_close(hdev);
     stop_hw:
     	hid_hw_stop(hdev);
    +	if (kbd->backlight_dev) {
    +		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
    +	}
     	return ret;
     }
     
    @@ -457,13 +457,13 @@ static void appletb_kbd_remove(struct hid_device *hdev)
     	appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
     
     	input_unregister_handler(&kbd->inp_handler);
    +	hid_hw_close(hdev);
    +	hid_hw_stop(hdev);
    +
     	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
     		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
     	}
    -
    -	hid_hw_close(hdev);
    -	hid_hw_stop(hdev);
     }
     
     static int appletb_kbd_suspend(struct hid_device *hdev, pm_message_t msg)
    -- 
    cgit 1.3-korg
    
    
    
4db2af929279

HID: appletb-kbd: fix UAF in inactivity-timer cleanup path

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSangyun KimApr 20, 2026Fixed in 7.1-rc4via kernel-cna
1 file changed · +8 9
  • drivers/hid/hid-appletb-kbd.c+8 9 modified
    diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c
    index 0fdc0968b9ef26..8feac9e3589b83 100644
    --- a/drivers/hid/hid-appletb-kbd.c
    +++ b/drivers/hid/hid-appletb-kbd.c
    @@ -440,13 +440,13 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
     unregister_handler:
     	input_unregister_handler(&kbd->inp_handler);
     close_hw:
    -	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
    -		timer_delete_sync(&kbd->inactivity_timer);
    -	}
     	hid_hw_close(hdev);
     stop_hw:
     	hid_hw_stop(hdev);
    +	if (kbd->backlight_dev) {
    +		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
    +	}
     	return ret;
     }
     
    @@ -457,13 +457,13 @@ static void appletb_kbd_remove(struct hid_device *hdev)
     	appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
     
     	input_unregister_handler(&kbd->inp_handler);
    +	hid_hw_close(hdev);
    +	hid_hw_stop(hdev);
    +
     	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
     		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
     	}
    -
    -	hid_hw_close(hdev);
    -	hid_hw_stop(hdev);
     }
     
     static int appletb_kbd_suspend(struct hid_device *hdev, pm_message_t msg)
    -- 
    cgit 1.3-korg
    
    
    
4db2af929279

HID: appletb-kbd: fix UAF in inactivity-timer cleanup path

1 file changed · +8 9
  • drivers/hid/hid-appletb-kbd.c+8 9 modified
    diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c
    index 0fdc0968b9ef26..8feac9e3589b83 100644
    --- a/drivers/hid/hid-appletb-kbd.c
    +++ b/drivers/hid/hid-appletb-kbd.c
    @@ -440,13 +440,13 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
     unregister_handler:
     	input_unregister_handler(&kbd->inp_handler);
     close_hw:
    -	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
    -		timer_delete_sync(&kbd->inactivity_timer);
    -	}
     	hid_hw_close(hdev);
     stop_hw:
     	hid_hw_stop(hdev);
    +	if (kbd->backlight_dev) {
    +		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
    +	}
     	return ret;
     }
     
    @@ -457,13 +457,13 @@ static void appletb_kbd_remove(struct hid_device *hdev)
     	appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
     
     	input_unregister_handler(&kbd->inp_handler);
    +	hid_hw_close(hdev);
    +	hid_hw_stop(hdev);
    +
     	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
     		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
     	}
    -
    -	hid_hw_close(hdev);
    -	hid_hw_stop(hdev);
     }
     
     static int appletb_kbd_suspend(struct hid_device *hdev, pm_message_t msg)
    -- 
    cgit 1.3-korg
    
    
    
59a79938ca55

HID: appletb-kbd: fix UAF in inactivity-timer cleanup path

1 file changed · +8 9
  • drivers/hid/hid-appletb-kbd.c+8 9 modified
    diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c
    index 0b10cff465e179..711403441e3089 100644
    --- a/drivers/hid/hid-appletb-kbd.c
    +++ b/drivers/hid/hid-appletb-kbd.c
    @@ -440,13 +440,13 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
     unregister_handler:
     	input_unregister_handler(&kbd->inp_handler);
     close_hw:
    -	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
    -		timer_delete_sync(&kbd->inactivity_timer);
    -	}
     	hid_hw_close(hdev);
     stop_hw:
     	hid_hw_stop(hdev);
    +	if (kbd->backlight_dev) {
    +		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
    +	}
     	return ret;
     }
     
    @@ -457,13 +457,13 @@ static void appletb_kbd_remove(struct hid_device *hdev)
     	appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
     
     	input_unregister_handler(&kbd->inp_handler);
    +	hid_hw_close(hdev);
    +	hid_hw_stop(hdev);
    +
     	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
     		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
     	}
    -
    -	hid_hw_close(hdev);
    -	hid_hw_stop(hdev);
     }
     
     #ifdef CONFIG_PM
    -- 
    cgit 1.3-korg
    
    
    
93d989e47bc3

HID: appletb-kbd: fix UAF in inactivity-timer cleanup path

1 file changed · +8 9
  • drivers/hid/hid-appletb-kbd.c+8 9 modified
    diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c
    index 0fdc0968b9ef26..8feac9e3589b83 100644
    --- a/drivers/hid/hid-appletb-kbd.c
    +++ b/drivers/hid/hid-appletb-kbd.c
    @@ -440,13 +440,13 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
     unregister_handler:
     	input_unregister_handler(&kbd->inp_handler);
     close_hw:
    -	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
    -		timer_delete_sync(&kbd->inactivity_timer);
    -	}
     	hid_hw_close(hdev);
     stop_hw:
     	hid_hw_stop(hdev);
    +	if (kbd->backlight_dev) {
    +		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
    +	}
     	return ret;
     }
     
    @@ -457,13 +457,13 @@ static void appletb_kbd_remove(struct hid_device *hdev)
     	appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
     
     	input_unregister_handler(&kbd->inp_handler);
    +	hid_hw_close(hdev);
    +	hid_hw_stop(hdev);
    +
     	if (kbd->backlight_dev) {
    -		put_device(&kbd->backlight_dev->dev);
     		timer_delete_sync(&kbd->inactivity_timer);
    +		put_device(&kbd->backlight_dev->dev);
     	}
    -
    -	hid_hw_close(hdev);
    -	hid_hw_stop(hdev);
     }
     
     static int appletb_kbd_suspend(struct hid_device *hdev, pm_message_t msg)
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Incorrect ordering of timer deletion, device put, and HID stop operations in the driver teardown path leaves the inactivity timer re-armed after it has been synchronously deleted, allowing a use-after-free of the backlight_device."

Attack vector

An attacker with physical access to a system using an Apple Touch Bar keyboard can trigger a use-after-free by causing a concurrent hid_appletb_bl unbind while the driver is being torn down [patch_id=2897707]. Window A occurs when put_device() is called before timer_delete_sync(), allowing a concurrent unbind to free the backlight_device between the two calls, after which the timer softirq accesses freed memory via mutex_lock() [patch_id=2897707]. Window B occurs because hid_hw_close()/hid_hw_stop() run after the timer is deleted, allowing a late HID .event callback (from USB URB completion) to re-arm the timer via reset_inactivity_timer(), which then fires on the about-to-be-freed backlight_device [patch_id=2897707]. Both windows manifest as a KASAN slab-use-after-free in __mutex_lock called from backlight_device_set_brightness via appletb_inactivity_timer [patch_id=2897707].

Affected code

The vulnerability is in drivers/hid/hid-appletb-kbd.c in the appletb_kbd_probe() close_hw error path and appletb_kbd_remove() function [patch_id=2897707]. Both functions had the inactivity timer deletion and backlight device put operations ordered incorrectly relative to each other and to hid_hw_close()/hid_hw_stop() [patch_id=2897707].

What the fix does

The patch reorders operations in both appletb_kbd_probe()'s close_hw error path and appletb_kbd_remove() to close both windows at once [patch_id=2897707]. First, hid_hw_close() and hid_hw_stop() are moved to execute before the backlight cleanup block, guaranteeing that no further HID .event callback can fire and re-arm the timer (closing Window B) [patch_id=2897707]. Second, within the backlight cleanup block, timer_delete_sync() is moved to run before put_device(), so the softirq is drained before the final reference is dropped (closing Window A) [patch_id=2897707].

Preconditions

  • configSystem must have an Apple Touch Bar keyboard (HID device) with the hid-appletb-kbd driver loaded
  • inputAttacker needs physical access to trigger USB URB completions or a concurrent hid_appletb_bl unbind
  • inputDriver teardown must be in progress (device removal or probe failure)

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

0

No linked articles in our index yet.