Re: [PATCH] HID: appletb-kbd: fix memory corruption of input_handler_list
From: Aditya Garg
Date: Fri Jun 27 2025 - 01:27:35 EST
On 27-06-2025 04:17 am, Qasim Ijaz wrote:
> In appletb_kbd_probe an input handler is initialised and then registered
> with input core through input_register_handler(). When this happens input
> core will add the input handler (specifically its node) to the global
> input_handler_list. The input_handler_list is central to the functionality
> of input core and is traversed in various places in input core. An example
> of this is when a new input device is plugged in and gets registered with
> input core.
>
> The input_handler in probe is allocated as device managed memory. If a
> probe failure occurs after input_register_handler() the input_handler
> memory is freed, yet it will remain in the input_handler_list. This
> effectively means the input_handler_list contains a dangling pointer
> to data belonging to a freed input handler.
>
> This causes an issue when any other input device is plugged in - in my
> case I had an old PixArt HP USB optical mouse and I decided to
> plug it in after a failure occurred after input_register_handler().
> This lead to the registration of this input device via
> input_register_device which involves traversing over every handler
> in the corrupted input_handler_list and calling input_attach_handler(),
> giving each handler a chance to bind to newly registered device.
>
> The core of this bug is a UAF which causes memory corruption of
> input_handler_list and to fix it we must ensure the input handler is
> unregistered from input core, this is done through
> input_unregister_handler().
>
> [ 63.191597] ==================================================================
> [ 63.192094] BUG: KASAN: slab-use-after-free in input_attach_handler.isra.0+0x1a9/0x1e0
> [ 63.192094] Read of size 8 at addr ffff888105ea7c80 by task kworker/0:2/54
> [ 63.192094]
> [ 63.192094] CPU: 0 UID: 0 PID: 54 Comm: kworker/0:2 Not tainted 6.16.0-rc2-00321-g2aa6621d
> [ 63.192094] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.164
> [ 63.192094] Workqueue: usb_hub_wq hub_event
> [ 63.192094] Call Trace:
> [ 63.192094] <TASK>
> [ 63.192094] dump_stack_lvl+0x53/0x70
> [ 63.192094] print_report+0xce/0x670
> [ 63.192094] ? input_attach_handler.isra.0+0x1a9/0x1e0
> [ 63.192094] kasan_report+0xce/0x100
> [ 63.192094] ? input_attach_handler.isra.0+0x1a9/0x1e0
> [ 63.192094] input_attach_handler.isra.0+0x1a9/0x1e0
> [ 63.192094] input_register_device+0x76c/0xd00
> [ 63.192094] hidinput_connect+0x686d/0xad60
> [ 63.192094] ? __pfx_hidinput_connect+0x10/0x10
> [ 63.192094] ? xhci_urb_enqueue+0x523/0x930
> [ 63.192094] hid_connect+0xf20/0x1b10
> [ 63.192094] ? mutex_unlock+0x7d/0xd0
> [ 63.192094] ? __pfx_mutex_unlock+0x10/0x10
> [ 63.192094] ? __pm_runtime_idle+0x95/0x1c0
> [ 63.192094] ? __pfx_hid_connect+0x10/0x10
> [ 63.192094] hid_hw_start+0x83/0x100
> [ 63.192094] hid_device_probe+0x2d1/0x680
> [ 63.192094] really_probe+0x1c3/0x690
> [ 63.192094] __driver_probe_device+0x247/0x300
> [ 63.192094] driver_probe_device+0x49/0x210
> [ 63.192094] __device_attach_driver+0x160/0x320
> [ 63.192094] ? __pfx___device_attach_driver+0x10/0x10
> [ 63.192094] bus_for_each_drv+0x10f/0x190
> [ 63.192094] ? __pfx_bus_for_each_drv+0x10/0x10
> [ 63.192094] __device_attach+0x18e/0x370
> [ 63.192094] ? __pfx___device_attach+0x10/0x10
> [ 63.192094] ? kobject_get+0x50/0xe0
> [ 63.192094] bus_probe_device+0x123/0x170
> [ 63.192094] device_add+0xd4d/0x1460
> [ 63.192094] ? __pfx_device_add+0x10/0x10
> [ 63.192094] ? up_write+0x4d/0x90
> [ 63.192094] ? __debugfs_create_file+0x377/0x5a0
> [ 63.192094] hid_add_device+0x30b/0x910
> [ 63.192094] ? __pfx_hid_add_device+0x10/0x10
> [ 63.192094] usbhid_probe+0x920/0xe00
> [ 63.192094] ? pm_runtime_enable+0xfa/0x2a0
> [ 63.192094] usb_probe_interface+0x363/0x9a0
> [ 63.192094] ? sysfs_do_create_link_sd+0x89/0x100
> [ 63.192094] really_probe+0x1c3/0x690
> [ 63.192094] __driver_probe_device+0x247/0x300
> [ 63.192094] driver_probe_device+0x49/0x210
> [ 63.192094] __device_attach_driver+0x160/0x320
> [ 63.192094] ? __pfx___device_attach_driver+0x10/0x10
> [ 63.192094] bus_for_each_drv+0x10f/0x190
> [ 63.192094] ? __pfx_bus_for_each_drv+0x10/0x10
> [ 63.192094] __device_attach+0x18e/0x370
> [ 63.192094] ? __pfx___device_attach+0x10/0x10
> [ 63.192094] ? kobject_get+0x50/0xe0
> [ 63.192094] bus_probe_device+0x123/0x170
> [ 63.192094] device_add+0xd4d/0x1460
> [ 63.192094] ? __pfx_device_add+0x10/0x10
> [ 63.192094] ? mutex_unlock+0x7d/0xd0
> [ 63.192094] ? __pfx_mutex_unlock+0x10/0x10
> [ 63.192094] usb_set_configuration+0xd14/0x1880
> [ 63.192094] usb_generic_driver_probe+0x78/0xb0
> [ 63.192094] usb_probe_device+0xaa/0x2e0
> [ 63.192094] really_probe+0x1c3/0x690
> [ 63.192094] __driver_probe_device+0x247/0x300
> [ 63.192094] ? usb_generic_driver_match+0x58/0x80
> [ 63.192094] driver_probe_device+0x49/0x210
> [ 63.192094] __device_attach_driver+0x160/0x320
> [ 63.192094] ? __pfx___device_attach_driver+0x10/0x10
> [ 63.192094] bus_for_each_drv+0x10f/0x190
> [ 63.192094] ? __pfx_bus_for_each_drv+0x10/0x10
> [ 63.192094] __device_attach+0x18e/0x370
> [ 63.192094] ? __pfx___device_attach+0x10/0x10
> [ 63.192094] ? kobject_get+0x50/0xe0
> [ 63.192094] bus_probe_device+0x123/0x170
> [ 63.192094] device_add+0xd4d/0x1460
> [ 63.192094] ? __pfx_device_add+0x10/0x10
> [ 63.192094] ? add_device_randomness+0xb2/0xe0
> [ 63.192094] usb_new_device+0x7b4/0x1000
> [ 63.192094] hub_event+0x234d/0x3fa0
> [ 63.192094] ? __pfx_hub_event+0x10/0x10
> [ 63.192094] ? _raw_spin_lock_irqsave+0x85/0xe0
> [ 63.192094] ? _raw_spin_lock_irqsave+0x85/0xe0
> [ 63.192094] ? mutex_unlock+0x7d/0xd0
> [ 63.192094] ? _raw_spin_lock_irq+0x80/0xe0
> [ 63.192094] ? __pfx__raw_spin_lock_irq+0x10/0x10
> [ 63.192094] ? __pm_runtime_suspend+0x74/0x1c0
> [ 63.192094] process_one_work+0x5bf/0xfe0
> [ 63.192094] worker_thread+0x777/0x13a0
> [ 63.192094] ? __kthread_parkme+0x99/0x180
> [ 63.192094] ? __pfx_worker_thread+0x10/0x10
> [ 63.192094] kthread+0x327/0x630
> [ 63.192094] ? __pfx_kthread+0x10/0x10
> [ 63.192094] ? __pfx__raw_spin_lock_irq+0x10/0x10
> [ 63.192094] ? __pfx_kthread+0x10/0x10
> [ 63.192094] ? __pfx_kthread+0x10/0x10
> [ 63.192094] ret_from_fork+0xff/0x1a0
> [ 63.192094] ? __pfx_kthread+0x10/0x10
> [ 63.192094] ret_from_fork_asm+0x1a/0x30
> [ 63.192094] </TASK>
> [ 63.192094]
> [ 63.192094] Allocated by task 54:
> [ 63.192094] kasan_save_stack+0x33/0x60
> [ 63.192094] kasan_save_track+0x14/0x30
> [ 63.192094] __kasan_kmalloc+0x8f/0xa0
> [ 63.192094] __kmalloc_node_track_caller_noprof+0x195/0x420
> [ 63.192094] devm_kmalloc+0x74/0x1e0
> [ 63.192094] appletb_kbd_probe+0x39/0x440
> [ 63.192094] hid_device_probe+0x2d1/0x680
> [ 63.192094] really_probe+0x1c3/0x690
> [ 63.192094] __driver_probe_device+0x247/0x300
> [ 63.192094] driver_probe_device+0x49/0x210
> [ 63.192094] __device_attach_driver+0x160/0x320
> [...]
> [ 63.192094]
> [ 63.192094] Freed by task 54:
> [ 63.192094] kasan_save_stack+0x33/0x60
> [ 63.192094] kasan_save_track+0x14/0x30
> [ 63.192094] kasan_save_free_info+0x3b/0x60
> [ 63.192094] __kasan_slab_free+0x37/0x50
> [ 63.192094] kfree+0xcf/0x360
> [ 63.192094] devres_release_group+0x1f8/0x3c0
> [ 63.192094] hid_device_probe+0x315/0x680
> [ 63.192094] really_probe+0x1c3/0x690
> [ 63.192094] __driver_probe_device+0x247/0x300
> [ 63.192094] driver_probe_device+0x49/0x210
> [ 63.192094] __device_attach_driver+0x160/0x320
> [...]
>
> Fixes: 93a0fc489481 ("HID: hid-appletb-kbd: add support for automatic brightness control while using the touchbar")
The handler was introduced in 7d62ba8deacf ("HID: hid-appletb-kbd: add support for fn toggle between media and function mode")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Qasim Ijaz <qasdev00@xxxxxxxxx>
> ---
> drivers/hid/hid-appletb-kbd.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c
> index d11c49665147..271d1b27b8dd 100644
> --- a/drivers/hid/hid-appletb-kbd.c
> +++ b/drivers/hid/hid-appletb-kbd.c
> @@ -430,13 +430,15 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
> ret = appletb_kbd_set_mode(kbd, appletb_tb_def_mode);
> if (ret) {
> dev_err_probe(dev, ret, "Failed to set touchbar mode\n");
> - goto close_hw;
> + goto unregister_handler;
> }
>
> hid_set_drvdata(hdev, kbd);
>
> return 0;
>
> +unregister_handler:
> + input_unregister_handler(&kbd->inp_handler);
> close_hw:
> if (kbd->backlight_dev) {
> put_device(&kbd->backlight_dev->dev);
This makes sense. With the "Fixes:" corrected in commit message,
Reviewed-by: Aditya Garg <gargaditya08@xxxxxxxx>