| From stable+bounces-317406-greg=kroah.com@vger.kernel.org Mon Sep 7 22:07:14 2026 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 7 Sep 2026 16:00:36 -0400 |
| Subject: HID: sony: clean up device list on probe failure |
| To: stable@vger.kernel.org |
| Cc: Doruk Tan Ozturk <doruk@0sec.ai>, Jiri Kosina <jkosina@suse.com>, Sasha Levin <sashal@kernel.org> |
| Message-ID: <20260907200036.328038-2-sashal@kernel.org> |
| |
| From: Doruk Tan Ozturk <doruk@0sec.ai> |
| |
| [ Upstream commit 7c65699a3a311198a07659a614fe64d45924839e ] |
| |
| sony_input_configured() adds some controllers to sony_device_list before |
| HID core registers their input devices. input_register_device() can fail |
| after the callback returns successfully. sony_probe() then observes that |
| HID_CLAIMED_INPUT is clear and unwinds, but only stops the HID hardware. |
| The devres-managed sony_sc is freed while its list node remains linked, so |
| the next matching controller traverses freed memory. |
| |
| Initialize the list node and device ID to inactive states. Make list |
| removal idempotent and run the driver-private cleanup on every probe |
| failure path. This also makes a second cleanup safe when |
| sony_input_configured() already unwound a partial initialization before |
| sony_probe() handles the missing input claim. |
| |
| Found by 0sec (https://0sec.ai) using automated source analysis; |
| verified against the HID input registration and probe unwind paths. |
| |
| Fixes: 4f967f6d7374 ("HID: sony: Fix memory issue when connecting device using both Bluetooth and USB") |
| Cc: stable@vger.kernel.org |
| Reported-by: Doruk Tan Ozturk <doruk@0sec.ai> |
| Link: https://lore.kernel.org/linux-input/20260724143925.007D61F00A3A@smtp.kernel.org/ |
| Assisted-by: 0sec:multi-model |
| Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai> |
| Signed-off-by: Jiri Kosina <jkosina@suse.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/hid/hid-sony.c | 33 +++++++++++++++++---------------- |
| 1 file changed, 17 insertions(+), 16 deletions(-) |
| |
| --- a/drivers/hid/hid-sony.c |
| +++ b/drivers/hid/hid-sony.c |
| @@ -1741,11 +1741,10 @@ out: |
| |
| static void sony_remove_dev_list(struct sony_sc *sc) |
| { |
| - if (sc->list_node.next) { |
| - scoped_guard(spinlock_irqsave, &sony_dev_list_lock) { |
| - list_del(&(sc->list_node)); |
| - } |
| - } |
| + guard(spinlock_irqsave)(&sony_dev_list_lock); |
| + |
| + if (!list_empty(&sc->list_node)) |
| + list_del_init(&sc->list_node); |
| } |
| |
| static int sony_get_bt_devaddr(struct sony_sc *sc) |
| @@ -1880,6 +1879,13 @@ static inline void sony_cancel_work_sync |
| } |
| } |
| |
| +static void sony_cleanup(struct sony_sc *sc) |
| +{ |
| + sony_cancel_work_sync(sc); |
| + sony_remove_dev_list(sc); |
| + sony_release_device_id(sc); |
| +} |
| + |
| static int sony_input_configured(struct hid_device *hdev, |
| struct hid_input *hidinput) |
| { |
| @@ -2038,9 +2044,7 @@ static int sony_input_configured(struct |
| err_close: |
| hid_hw_close(hdev); |
| err_stop: |
| - sony_cancel_work_sync(sc); |
| - sony_remove_dev_list(sc); |
| - sony_release_device_id(sc); |
| + sony_cleanup(sc); |
| return ret; |
| } |
| |
| @@ -2066,6 +2070,8 @@ static int sony_probe(struct hid_device |
| } |
| |
| spin_lock_init(&sc->lock); |
| + INIT_LIST_HEAD(&sc->list_node); |
| + sc->device_id = -1; |
| |
| sc->quirks = quirks; |
| hid_set_drvdata(hdev, sc); |
| @@ -2094,6 +2100,7 @@ static int sony_probe(struct hid_device |
| ret = hid_hw_start(hdev, connect_mask); |
| if (ret) { |
| hid_err(hdev, "hw start failed\n"); |
| + sony_cleanup(sc); |
| return ret; |
| } |
| |
| @@ -2145,7 +2152,7 @@ static int sony_probe(struct hid_device |
| |
| err: |
| usb_free_urb(sc->ghl_urb); |
| - |
| + sony_cleanup(sc); |
| hid_hw_stop(hdev); |
| return ret; |
| } |
| @@ -2162,13 +2169,7 @@ static void sony_remove(struct hid_devic |
| } |
| |
| hid_hw_close(hdev); |
| - |
| - sony_cancel_work_sync(sc); |
| - |
| - sony_remove_dev_list(sc); |
| - |
| - sony_release_device_id(sc); |
| - |
| + sony_cleanup(sc); |
| hid_hw_stop(hdev); |
| } |
| |