From 337bdf853101a0ee66eadf668f0fef21f8276b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Fri, 14 Aug 2026 07:05:20 +0000 Subject: [PATCH] PCI/sysfs: Decouple acpi_index from the optional device name element MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "_DSM for Naming a PCI or PCI Express Device Under Operating Systems" (PCI Firmware r3.3, sec 4.6.7) returns a package of two elements: 1) Instance number (mandatory Integer) 2) String name (optional String, null string if not populated) These are exposed as sysfs 'acpi_index' and 'label'. Previously, if the name was malformed, reads of 'acpi_index' failed unnecessarily. Validate each element only for the attribute that exports it. So "acpi_index" now depends on the instance number alone, and "label" reads fail with -EIO when the name element is neither a string nor a buffer. The package elements pointer is read only after the object type has been checked. On platforms with a valid instance number and a malformed name element the "acpi_index" attribute starts returning data. Because udev derives the onboard interface name from "acpi_index", an interface on such a platform may be renamed once, on the first boot after this change. That is the attribute assuming the value the firmware always provided. Link: https://github.com/pciutils/pciutils/issues/175 Signed-off-by: Krzysztof WilczyƄski [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260814070522.2327975-3-kwilczynski@kernel.org --- drivers/pci/pci-label.c | 55 +++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index 255e0ecffb09..5b08f50653a3 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c @@ -157,7 +157,7 @@ static int dsm_get_label(struct device *dev, char *buf, { acpi_handle handle = ACPI_HANDLE(dev); union acpi_object *obj, *tmp; - int len = 0; + int len; if (!handle) return -ENODEV; @@ -167,30 +167,43 @@ static int dsm_get_label(struct device *dev, char *buf, if (!obj) return -EIO; - tmp = obj->package.elements; - if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 && - tmp[0].type == ACPI_TYPE_INTEGER && - (tmp[1].type == ACPI_TYPE_STRING || - tmp[1].type == ACPI_TYPE_BUFFER)) { - /* - * The second string element is optional even when - * this _DSM is implemented; when not implemented, - * this entry must return a null string. - */ - if (attr == ACPI_ATTR_INDEX_SHOW) { - len = sysfs_emit(buf, "%llu\n", tmp->integer.value); - } else if (attr == ACPI_ATTR_LABEL_SHOW) { - if (tmp[1].type == ACPI_TYPE_STRING) - len = sysfs_emit(buf, "%s\n", - tmp[1].string.pointer); - else if (tmp[1].type == ACPI_TYPE_BUFFER) - len = dsm_label_utf16s_to_utf8s(tmp + 1, buf); - } + if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 2) { + len = -EIO; + goto out; } + tmp = obj->package.elements; + if (tmp[0].type != ACPI_TYPE_INTEGER) { + len = -EIO; + goto out; + } + + if (attr == ACPI_ATTR_INDEX_SHOW) { + len = sysfs_emit(buf, "%llu\n", tmp[0].integer.value); + goto out; + } + + /* + * Per PCI Firmware r3.3, sec 4.6.7, the device name is optional + * even when this _DSM is implemented. When not implemented, this + * entry must return a NULL string. + */ + switch (tmp[1].type) { + case ACPI_TYPE_STRING: + len = sysfs_emit(buf, "%s\n", tmp[1].string.pointer); + break; + case ACPI_TYPE_BUFFER: + len = dsm_label_utf16s_to_utf8s(&tmp[1], buf); + break; + default: + len = -EIO; + break; + } + +out: ACPI_FREE(obj); - return len > 0 ? len : -EIO; + return len; } static ssize_t label_show(struct device *dev, struct device_attribute *attr,