[PATCH OLK-5.10 V1 0/3] Fix CVE-2026-90329
CVE-2026-90329 fix has 2 dependencies. Dmitry Torokhov (2): HID: split apart hid_device_probe to make logic more apparent HID: ensure timely release of driver-allocated resources Yousef Alhouseen (1): HID: synchronize input before cleaning up a failed probe drivers/hid/hid-core.c | 120 +++++++++++++++++++++++++---------------- include/linux/hid.h | 1 + 2 files changed, 74 insertions(+), 47 deletions(-) -- 2.34.1
From: Dmitry Torokhov <dmitry.torokhov@gmail.com> stable inclusion from stable-v5.10.270 commit e51882f2bf470ef77484ebd3b648553173253511 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19484 CVE: CVE-2026-90329 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit 207733f9266194b3cd90ddae723a1f82eb64030b ] hid_device_probe() has a complex flow and locks and unlocks a mutex. Move the most of the logic into __hid_device_probe() and hid_check_device_match() and leave the locking in hid_device_probe() which makes the code more clear. Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Stable-dep-of: 207853d46f7e ("HID: synchronize input before cleaning up a failed probe") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Yao Yiqi <yaoyiqi3@huawei.com> --- drivers/hid/hid-core.c | 101 ++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b17bdbc9d2a7..31378bb8c559 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2283,64 +2283,71 @@ bool hid_compare_device_paths(struct hid_device *hdev_a, } EXPORT_SYMBOL_GPL(hid_compare_device_paths); +static bool hid_check_device_match(struct hid_device *hdev, + struct hid_driver *hdrv, + const struct hid_device_id **id) +{ + *id = hid_match_device(hdev, hdrv); + if (!*id) + return -ENODEV; + + if (hdrv->match) + return hdrv->match(hdev, hid_ignore_special_drivers); + + /* + * hid-generic implements .match(), so we must be dealing with a + * different HID driver here, and can simply check if + * hid_ignore_special_drivers is set or not. + */ + return !hid_ignore_special_drivers; +} + +static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv) +{ + const struct hid_device_id *id; + int ret; + + if (!hid_check_device_match(hdev, hdrv, &id)) + return -ENODEV; + + /* reset the quirks that has been previously set */ + hdev->quirks = hid_lookup_quirk(hdev); + hdev->driver = hdrv; + + if (hdrv->probe) { + ret = hdrv->probe(hdev, id); + } else { /* default probe */ + ret = hid_open_report(hdev); + if (!ret) + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + } + + if (ret) { + hid_close_report(hdev); + hdev->driver = NULL; + } + + return ret; +} + static int hid_device_probe(struct device *dev) { - struct hid_driver *hdrv = to_hid_driver(dev->driver); struct hid_device *hdev = to_hid_device(dev); - const struct hid_device_id *id; + struct hid_driver *hdrv = to_hid_driver(dev->driver); int ret = 0; - if (down_interruptible(&hdev->driver_input_lock)) { - ret = -EINTR; - goto end; - } - hdev->io_started = false; + if (down_interruptible(&hdev->driver_input_lock)) + return -EINTR; + hdev->io_started = false; clear_bit(ffs(HID_STAT_REPROBED), &hdev->status); - if (!hdev->driver) { - id = hid_match_device(hdev, hdrv); - if (id == NULL) { - ret = -ENODEV; - goto unlock; - } + if (!hdev->driver) + ret = __hid_device_probe(hdev, hdrv); - if (hdrv->match) { - if (!hdrv->match(hdev, hid_ignore_special_drivers)) { - ret = -ENODEV; - goto unlock; - } - } else { - /* - * hid-generic implements .match(), so if - * hid_ignore_special_drivers is set, we can safely - * return. - */ - if (hid_ignore_special_drivers) { - ret = -ENODEV; - goto unlock; - } - } - - /* reset the quirks that has been previously set */ - hdev->quirks = hid_lookup_quirk(hdev); - hdev->driver = hdrv; - if (hdrv->probe) { - ret = hdrv->probe(hdev, id); - } else { /* default probe */ - ret = hid_open_report(hdev); - if (!ret) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - } - if (ret) { - hid_close_report(hdev); - hdev->driver = NULL; - } - } -unlock: if (!hdev->io_started) up(&hdev->driver_input_lock); -end: + return ret; } -- 2.34.1
From: Dmitry Torokhov <dmitry.torokhov@gmail.com> stable inclusion from stable-v5.10.270 commit e6ea3de7abef998aaab9f04a7a11a7c5f56bbe57 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19484 CVE: CVE-2026-90239 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit 62c68e7cee332e08e625af3bca3318814086490d ] More and more drivers rely on devres to manage their resources, however if bus' probe() and release() methods are not trivial and control some of resources as well (for example enable or disable clocks, or attach device to a power domain), we need to make sure that driver-allocated resources are released immediately after driver's remove() method returns, and not postponed until driver core gets around to releasing resources. In case of HID we should not try to close the report and release associated memory until after all devres callbacks are executed. To fix that we open a new devres group before calling driver's probe() and explicitly release it when we return from driver's remove(). This is similar to what we did for I2C bus in commit 5b5475826c52 ("i2c: ensure timely release of driver-allocated resources"). It is tempting to try and move this into driver core, but actually doing so is challenging, we need to split bus' remove() method into pre- and post-remove methods, which would make the logic even less clear. Reported-by: Stephen Boyd <swboyd@chromium.org> Link: https://lore.kernel.org/r/20230505232417.1377393-1-swboyd@chromium.org Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Stable-dep-of: 207853d46f7e ("HID: synchronize input before cleaning up a failed probe") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Yao Yiqi <yaoyiqi3@huawei.com> --- drivers/hid/hid-core.c | 17 +++++++++++++++++ include/linux/hid.h | 1 + 2 files changed, 18 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 31378bb8c559..934d782b42b8 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2310,6 +2310,10 @@ static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv) if (!hid_check_device_match(hdev, hdrv, &id)) return -ENODEV; + hdev->devres_group_id = devres_open_group(&hdev->dev, NULL, GFP_KERNEL); + if (!hdev->devres_group_id) + return -ENOMEM; + /* reset the quirks that has been previously set */ hdev->quirks = hid_lookup_quirk(hdev); hdev->driver = hdrv; @@ -2322,7 +2326,16 @@ static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv) ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); } + /* + * Note that we are not closing the devres group opened above so + * even resources that were attached to the device after probe is + * run are released when hid_device_remove() is executed. This is + * needed as some drivers would allocate additional resources, + * for example when updating firmware. + */ + if (ret) { + devres_release_group(&hdev->dev, hdev->devres_group_id); hid_close_report(hdev); hdev->driver = NULL; } @@ -2365,6 +2378,10 @@ static int hid_device_remove(struct device *dev) hdrv->remove(hdev); else /* default remove */ hid_hw_stop(hdev); + + /* Release all devres resources allocated by the driver */ + devres_release_group(&hdev->dev, hdev->devres_group_id); + hid_close_report(hdev); hdev->driver = NULL; } diff --git a/include/linux/hid.h b/include/linux/hid.h index ab56fffb74a2..bb128a3dee63 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -570,6 +570,7 @@ struct hid_device { /* device report descriptor */ struct semaphore driver_input_lock; /* protects the current driver */ struct device dev; /* device */ struct hid_driver *driver; + void *devres_group_id; /* ID of probe devres group */ struct hid_ll_driver *ll_driver; struct mutex ll_open_lock; -- 2.34.1
From: Yousef Alhouseen <alhouseenyousef@gmail.com> stable inclusion from stable-v5.10.270 commit 3ffb088a2ed34ca982cfc2c81d107ce370aa45f1 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19484 CVE: CVE-2026-90329 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit 207853d46f7ef2e28042344a1468da8754c3ddbf ] hid_device_io_start() allows reports to run concurrently with probe. If the probe subsequently fails, __hid_device_probe() releases driver resources and clears hdev->driver without first excluding those report callbacks. For example, a report may enter hidraw_report_event() while the failure path frees the associated hidraw object, leading to a use-after-free when the report takes the object's list lock. Stop input before performing failed-probe cleanup. This reacquires driver_input_lock and waits for any report callback already in progress. Fixes: c849a6143bec ("HID: Separate struct hid_device's driver_lock into two locks.") Reported-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=9eebf5f6544c5e873858 Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Yao Yiqi <yaoyiqi3@huawei.com> --- drivers/hid/hid-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 934d782b42b8..d97e3fb5d350 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2335,6 +2335,8 @@ static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv) */ if (ret) { + if (hdev->io_started) + hid_device_io_stop(hdev); devres_release_group(&hdev->dev, hdev->devres_group_id); hid_close_report(hdev); hdev->driver = NULL; -- 2.34.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/28457 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/IFO... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/28457 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/IFO...
participants (2)
-
patchwork bot -
Yao Yiqi