[PATCH OLK-6.6 0/3] CVE-2026-53120
CVE-2026-53120 Danilo Krummrich (1): PCI: use generic driver_override infrastructure Samiullah Khawaja (1): PCI: Initialize temporary device in new_id_store() Ziming Du (1): PCI: fix kabi breakage due to driver_override removal drivers/pci/pci-driver.c | 20 +++++++++++++++----- drivers/pci/pci-sysfs.c | 28 ---------------------------- drivers/pci/probe.c | 1 - drivers/vfio/pci/vfio_pci_core.c | 4 ++-- drivers/xen/xen-pciback/pci_stub.c | 6 ++++-- include/linux/pci.h | 7 +------ 6 files changed, 22 insertions(+), 44 deletions(-) -- 2.43.0
From: Danilo Krummrich <dakr@kernel.org> mainline inclusion from mainline-v7.1-rc1 commit 10a4206a24013be4d558d476010cbf2eb4c9fa64 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15817 CVE: CVE-2026-53120 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- When a driver is probed through __driver_attach(), the bus' match() callback is called without the device lock held, thus accessing the driver_override field without a lock, which can cause a UAF. Fix this by using the driver-core driver_override infrastructure taking care of proper locking internally. Note that calling match() from __driver_attach() without the device lock held is intentional. [1] Link: https://lore.kernel.org/driver-core/DGRGTIRHA62X.3RY09D9SOK77P@kernel.org/ [1] Reported-by: Gui-Dong Han <hanguidong02@gmail.com> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789 Fixes: 782a985d7af2 ("PCI: Introduce new device binding path using pci_dev.driver_override") Acked-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Alex Williamson <alex@shazbot.org> Tested-by: Gui-Dong Han <hanguidong02@gmail.com> Reviewed-by: Gui-Dong Han <hanguidong02@gmail.com> Link: https://patch.msgid.link/20260324005919.2408620-6-dakr@kernel.org Signed-off-by: Danilo Krummrich <dakr@kernel.org> Conflicts: drivers/vfio/pci/vfio_pci_core.c drivers/pci/pci-driver.c include/linux/pci.h [Ziming Du: context conflict] Signed-off-by: Ziming Du <duziming2@huawei.com> --- drivers/pci/pci-driver.c | 11 +++++++---- drivers/pci/pci-sysfs.c | 28 ---------------------------- drivers/pci/probe.c | 1 - drivers/vfio/pci/vfio_pci_core.c | 4 ++-- drivers/xen/xen-pciback/pci_stub.c | 6 ++++-- include/linux/pci.h | 6 ------ 6 files changed, 13 insertions(+), 43 deletions(-) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index aea17e0316130..7a186037ee619 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -138,9 +138,11 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv, { struct pci_dynid *dynid; const struct pci_device_id *found_id = NULL, *ids; + int ret; /* When driver_override is set, only bind to the matching driver */ - if (dev->driver_override && strcmp(dev->driver_override, drv->name)) + ret = device_match_driver_override(&dev->dev, &drv->driver); + if (ret == 0) return NULL; /* Look at the dynamic ids first, before the static ones */ @@ -164,7 +166,7 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv, * matching. */ if (found_id->override_only) { - if (dev->driver_override) + if (ret > 0) return found_id; } else { return found_id; @@ -172,7 +174,7 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv, } /* driver_override will always match, send a dummy id */ - if (dev->driver_override) + if (ret > 0) return &pci_device_id_any; return NULL; } @@ -432,7 +434,7 @@ void __weak pcibios_free_irq(struct pci_dev *dev) static inline bool pci_device_can_probe(struct pci_dev *pdev) { return (!pdev->is_virtfn || pdev->physfn->sriov->drivers_autoprobe || - pdev->driver_override); + device_has_driver_override(&pdev->dev)); } #else static inline bool pci_device_can_probe(struct pci_dev *pdev) @@ -1693,6 +1695,7 @@ static void pci_dma_cleanup(struct device *dev) struct bus_type pci_bus_type = { .name = "pci", + .driver_override = true, .match = pci_bus_match, .uevent = pci_uevent, .probe = pci_device_probe, diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index a9f2b083afd5c..d1711d49d824c 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -635,33 +635,6 @@ static ssize_t devspec_show(struct device *dev, static DEVICE_ATTR_RO(devspec); #endif -static ssize_t driver_override_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int ret; - - ret = driver_set_override(dev, &pdev->driver_override, buf, count); - if (ret) - return ret; - - return count; -} - -static ssize_t driver_override_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pci_dev *pdev = to_pci_dev(dev); - ssize_t len; - - device_lock(dev); - len = sysfs_emit(buf, "%s\n", pdev->driver_override); - device_unlock(dev); - return len; -} -static DEVICE_ATTR_RW(driver_override); - static struct attribute *pci_dev_attrs[] = { &dev_attr_power_state.attr, &dev_attr_resource.attr, @@ -689,7 +662,6 @@ static struct attribute *pci_dev_attrs[] = { #ifdef CONFIG_OF &dev_attr_devspec.attr, #endif - &dev_attr_driver_override.attr, &dev_attr_ari_enabled.attr, NULL, }; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 52352478848e6..f3ef90f697c36 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2421,7 +2421,6 @@ static void pci_release_dev(struct device *dev) pci_release_of_node(pci_dev); pcibios_release_device(pci_dev); pci_bus_put(pci_dev->bus); - kfree(pci_dev->driver_override); bitmap_free(pci_dev->dma_alias_mask); dev_dbg(dev, "device released\n"); kfree(pci_dev); diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index b7ef86f3f0d01..172339bc4dbdf 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -2094,8 +2094,8 @@ static int vfio_pci_bus_notifier(struct notifier_block *nb, pdev->is_virtfn && physfn == vdev->pdev) { pci_info(vdev->pdev, "Captured SR-IOV VF %s driver_override\n", pci_name(pdev)); - pdev->driver_override = kasprintf(GFP_KERNEL, "%s", - vdev->vdev.ops->name); + device_set_driver_override(&pdev->dev, + vdev->vdev.ops->name); } else if (action == BUS_NOTIFY_BOUND_DRIVER && pdev->is_virtfn && physfn == vdev->pdev) { struct pci_driver *drv = pci_dev_driver(pdev); diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index e34b623e4b41f..42e630239b9b0 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -555,6 +555,8 @@ static int pcistub_seize(struct pci_dev *dev, return err; } +static struct pci_driver xen_pcibk_pci_driver; + /* Called when 'bind'. This means we must _NOT_ call pci_reset_function or * other functions that take the sysfs lock. */ static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id) @@ -566,8 +568,8 @@ static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id) match = pcistub_match(dev); - if ((dev->driver_override && - !strcmp(dev->driver_override, PCISTUB_DRIVER_NAME)) || + if (device_match_driver_override(&dev->dev, + &xen_pcibk_pci_driver.driver) > 0 || match) { if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL diff --git a/include/linux/pci.h b/include/linux/pci.h index b95e85c1c5e9e..a8320b6b70f42 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -521,12 +521,6 @@ struct pci_dev { u16 acs_cap; /* ACS Capability offset */ phys_addr_t rom; /* Physical address if not from BAR */ size_t romlen; /* Length if not from BAR */ - /* - * Driver name to force a match. Do not set directly, because core - * frees it. Use driver_set_override() to set or clear it. - */ - const char *driver_override; - unsigned long priv_flags; /* Private flags for the PCI driver */ /* These methods index pci_reset_fn_methods[] */ -- 2.43.0
Offering: HULK hulk inclusion category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15817 CVE: CVE-2026-53120 -------------------------------- Add driver_override back to fix kabi broken. Fixes: 10a4206a2401 ("PCI: use generic driver_override infrastructure") Signed-off-by: Ziming Du <duziming2@huawei.com> --- include/linux/pci.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pci.h b/include/linux/pci.h index a8320b6b70f42..510cfa83f270c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -521,6 +521,7 @@ struct pci_dev { u16 acs_cap; /* ACS Capability offset */ phys_addr_t rom; /* Physical address if not from BAR */ size_t romlen; /* Length if not from BAR */ + KABI_DEPRECATE(const char *, driver_override) unsigned long priv_flags; /* Private flags for the PCI driver */ /* These methods index pci_reset_fn_methods[] */ -- 2.43.0
From: Samiullah Khawaja <skhawaja@google.com> mainline inclusion from mainline-v7.1-rc3 commit f45a49a2380a47332817b7248c61a0ebbc6f0d00 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15817 CVE: CVE-2026-53120 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- When setting new_id of a PCI device driver using sysfs a lockdep splat occurs. This is because new_id_store() builds a temporary pci_dev for pci_match_device(), which calls device_match_driver_override(). That depends on the driver_override.lock added by cb3d1049f4ea ("driver core: generalize driver_override in struct device"). The new driver_override.lock was not initialized in the temporary pci_dev, resulting in this lockdep splat. Initialize the temporary pci_dev to fix this. Repro: Build with CONFIG_LOCKDEP=y, boot with QEMU, and add a new ID: # echo "8086 10f5" > /sys/bus/pci/drivers/e1000e/new_id INFO: trying to register non-static key. The code is fine but needs lockdep annotation, or maybe you didn't initialize this object before use? turning off the locking correctness validator. CPU: 2 UID: 0 PID: 177 Comm: liveupdate-iomm Not tainted 7.0.0+ #9 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x5d/0x80 register_lock_class+0x77e/0x790 lock_acquire+0xbf/0x2e0 pci_match_device+0x24/0x180 new_id_store+0x189/0x1d0 kernfs_fop_write_iter+0x14f/0x210 vfs_write+0x263/0x5e0 ksys_write+0x79/0xf0 do_syscall_64+0x117/0xf80 Fixes: 10a4206a2401 ("PCI: use generic driver_override infrastructure") Fixes: 8895d3bcb8ba ("PCI: Fail new_id for vendor/device values already built into driver") Signed-off-by: Samiullah Khawaja <skhawaja@google.com> [bhelgaas: add commit log details and repro, trim backtrace] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Danilo Krummrich <dakr@kernel.org> Link: https://patch.msgid.link/20260505234327.716630-1-skhawaja@google.com Signed-off-by: Ziming Du <duziming2@huawei.com> --- drivers/pci/pci-driver.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 7a186037ee619..4caf1e8a94a12 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -179,6 +179,11 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv, return NULL; } +static void _pci_free_device(struct device *dev) +{ + kfree(to_pci_dev(dev)); +} + /** * new_id_store - sysfs frontend to pci_add_dynid() * @driver: target device driver @@ -214,11 +219,13 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf, pdev->subsystem_vendor = subvendor; pdev->subsystem_device = subdevice; pdev->class = class; + pdev->dev.release = _pci_free_device; + device_initialize(&pdev->dev); if (pci_match_device(pdrv, pdev)) retval = -EEXIST; - kfree(pdev); + put_device(&pdev->dev); if (retval) return retval; -- 2.43.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/25781 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/REQ... 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/25781 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/REQ...
participants (2)
-
patchwork bot -
Ziming Du