From: Michal Wajdeczko michal.wajdeczko@intel.com
[ Upstream commit 400a6da1e967c4f117e4757412df06dcfaea0e6a ]
While we expect config directory names to match PCI device name, currently we are only scanning provided names for domain, bus, device and function numbers, without checking their format. This would pass slightly broken entries like:
/sys/kernel/config/xe/ ├── 0000:00:02.0000000000000 │ └── ... ├── 0000:00:02.0x │ └── ... ├── 0: 0: 2. 0 │ └── ... └── 0:0:2.0 └── ...
To avoid such mistakes, check if the name provided exactly matches the canonical PCI device address format, which we recreated from the parsed BDF data. Also simplify scanf format as it can't really catch all formatting errors.
Signed-off-by: Michal Wajdeczko michal.wajdeczko@intel.com Cc: Lucas De Marchi lucas.demarchi@intel.com Reviewed-by: Lucas De Marchi lucas.demarchi@intel.com Link: https://lore.kernel.org/r/20250722141059.30707-3-michal.wajdeczko@intel.com Signed-off-by: Lucas De Marchi lucas.demarchi@intel.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES
**Why It’s A Bug** - Current code accepts any string that scans into domain/bus/slot/function, even if not in canonical PCI BDF format. See parsing in drivers/gpu/drm/xe/xe_configfs.c:264. - The driver later looks up the configfs group by constructing the canonical BDF name, so a misnamed directory cannot be found and settings silently don’t apply. See lookup formatting in drivers/gpu/drm/xe/xe_configfs.c:310-311. - The in-file docs already prescribe canonical names (for example 0000:03:00.0), reinforcing that non-canonical input is unintended; see example path in drivers/gpu/drm/xe/xe_configfs.c:41.
**Fix Details** - Parsing is relaxed to read numbers generically, then the code synthesizes the canonical BDF string and requires an exact match: - Replace strict-width `sscanf(name, "%04x:%02x:%02x.%x", ...)` with `sscanf(name, "%x:%x:%x.%x", ...)` to get the values. - Build the canonical name and enforce exact equality via `scnprintf(canonical, ..., "%04x:%02x:%02x.%d", ...)` and `strcmp(name, canonical) == 0`. Returns `-EINVAL` if it differs. - The canonical composition uses `PCI_SLOT(PCI_DEVFN(slot, function))` and `PCI_FUNC(...)`, implicitly constraining slot/function to valid bit widths and preventing odd encodings from slipping through. - The change is localized to group creation in drivers/gpu/drm/xe/xe_configfs.c:256 (the function where the new `canonical` buffer, `scnprintf`, and `strcmp` checks are added).
**User Impact Fixed** - Prevents creating “broken” directories like 0000:00:02.0000000000000, 0000:00:02.0x, 0:0:2.0, or with spaces/uppercase hex. Previously these were accepted, but the driver’s later lookup (by canonical name) would not find them, so configfs settings were ignored. - With this patch, such inputs fail fast with `-EINVAL` instead of failing silently later.
**Risk and Scope** - Small, contained change to a single function in the Xe configfs code; no architectural changes or core subsystem impact. - Maintains existing error behavior for non-existent devices (`-ENODEV` remains). - Behavior change is strictly tighter validation; correct canonical names continue to work. Scripts relying on non-canonical names would not have worked reliably anyway (lookups failed), so rejecting them is safer.
**Stable Backport Considerations** - Meets stable criteria: fixes a real user-visible misbehavior (silent no-op config), minimal patch size, confined to the Xe driver’s configfs path, no API/ABI changes. - No dependency on other features; headers used (`string.h`, PCI macros) are already present. Applies cleanly around drivers/gpu/drm/xe/xe_configfs.c:256-266. - Applicable to stable series that include Xe configfs (the file and functions present in this tree: drivers/gpu/drm/xe/xe_configfs.c:256 and drivers/gpu/drm/xe/xe_configfs.c:310).
In summary, this is a low-risk input validation fix that prevents silent misconfiguration and aligns behavior with documented usage. It is suitable for backporting to stable kernels that ship the Xe configfs interface.
drivers/gpu/drm/xe/xe_configfs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_configfs.c b/drivers/gpu/drm/xe/xe_configfs.c index 58c1f397c68c9..797508cc6eb17 100644 --- a/drivers/gpu/drm/xe/xe_configfs.c +++ b/drivers/gpu/drm/xe/xe_configfs.c @@ -259,12 +259,19 @@ static struct config_group *xe_config_make_device_group(struct config_group *gro unsigned int domain, bus, slot, function; struct xe_config_device *dev; struct pci_dev *pdev; + char canonical[16]; int ret;
- ret = sscanf(name, "%04x:%02x:%02x.%x", &domain, &bus, &slot, &function); + ret = sscanf(name, "%x:%x:%x.%x", &domain, &bus, &slot, &function); if (ret != 4) return ERR_PTR(-EINVAL);
+ ret = scnprintf(canonical, sizeof(canonical), "%04x:%02x:%02x.%d", domain, bus, + PCI_SLOT(PCI_DEVFN(slot, function)), + PCI_FUNC(PCI_DEVFN(slot, function))); + if (ret != 12 || strcmp(name, canonical)) + return ERR_PTR(-EINVAL); + pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function)); if (!pdev) return ERR_PTR(-ENODEV);