Re: [PATCH v3 6/8] HID: asus: prevent a late KEY_FN_ESC to trigger a use-after-free
From: Antheas Kapenekakis
Date: Sat Jun 13 2026 - 12:04:32 EST
On Sat, 13 Jun 2026 at 17:30, Denis Benato <denis.benato@xxxxxxxxx> wrote:
>
> A late KEY_FN_ESC event can trigger asus_event() and unconditionally call
> schedule_work() after the work was supposedly canceled.
>
> Once the driver is removed and drvdata is freed by devres, the workqueue
> could execute asus_sync_fn_lock() and dereference the freed drvdata.
>
> Fixes: f631011e36b8 ("HID: hid-asus: Implement fn lock for Asus ProArt P16")
> Reported-by: sahiko-bot@xxxxxxxxxx
> Signed-off-by: Denis Benato <denis.benato@xxxxxxxxx>
> ---
> drivers/hid/hid-asus.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
> index a6467172c455..a65a28137f0d 100644
> --- a/drivers/hid/hid-asus.c
> +++ b/drivers/hid/hid-asus.c
> @@ -148,6 +148,7 @@ struct asus_drvdata {
> int battery_stat;
> bool battery_in_query;
> unsigned long battery_next_query;
> + bool fn_lock_sync_work_disabled;
> struct work_struct fn_lock_sync_work;
> bool fn_lock;
> #if IS_REACHABLE(CONFIG_ASUS_WMI)
> @@ -416,7 +417,7 @@ static int asus_event(struct hid_device *hdev, struct hid_field *field,
> case KEY_KBDILLUMTOGGLE:
> return !asus_hid_event(ASUS_EV_BRTTOGGLE);
> case KEY_FN_ESC:
> - if (drvdata->quirks & QUIRK_HID_FN_LOCK) {
> + if (!drvdata->fn_lock_sync_work_disabled && (drvdata->quirks & QUIRK_HID_FN_LOCK)) {
> drvdata->fn_lock = !drvdata->fn_lock;
> schedule_work(&drvdata->fn_lock_sync_work);
> }
> @@ -1497,8 +1498,10 @@ static void asus_remove(struct hid_device *hdev)
> cancel_work_sync(&drvdata->kbd_backlight->work);
> }
>
> - if (drvdata->quirks & QUIRK_HID_FN_LOCK)
> + if (drvdata->quirks & QUIRK_HID_FN_LOCK) {
> + drvdata->fn_lock_sync_work_disabled = true;
> cancel_work_sync(&drvdata->fn_lock_sync_work);
> + }
I am not sure this is a real bug. can _event be called during _remove?
Doesn't the core prevent that?
> #if IS_REACHABLE(CONFIG_ASUS_WMI)
> drvdata->wmi_work_disabled = true;
> --
> 2.47.3
>
>