[PATCH v8 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match()
From: Wei Wang
Date: Mon May 25 2026 - 09:44:30 EST
Callers of pci_dev_str_match() manually checked for the ';' or ','
delimiter and advanced the parameter pointer past it. Move this common
logic into pci_dev_str_match() so callers no longer need to duplicate it.
As a side effect of this consolidation, pci_dev_str_match() now enforces
stricter boundary checks on successful matches. Previously, if a user
provided a malformed parameter with garbage characters appended to a
valid BDF (e.g., "pci=config_acs=110x@0000:04:00.0foo"), the callers
would silently accept the prefix match and ignore the trailing garbage.
Now, pci_dev_str_match() strictly verifies that the matched token is
immediately followed by a valid delimiter (';', ',') or the null
terminator ('\0'), returning -EINVAL if it encounters invalid trailing
characters.
Signed-off-by: Wei Wang <wei.w.wang@xxxxxxxxxxx>
Reviewed-by: Jason Gunthorpe <jgg@xxxxxxxxxx>
---
drivers/pci/pci.c | 40 ++++++++++++++++++----------------------
1 file changed, 18 insertions(+), 22 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index ff7e1cbd6595..e9d39dbb117e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -334,7 +334,7 @@ static int pci_dev_str_match_path(struct pci_dev *dev, const char *path,
* pci_dev_str_match - test if a string matches a device
* @dev: the PCI device to test
* @p: string to match the device against
- * @endptr: pointer to the string after the match
+ * @endptr: pointer to the string after the match, with the delimiter skipped
*
* Test if a string (typically from a kernel parameter) matches a specified
* PCI device. The string may be of one of the following formats:
@@ -388,8 +388,13 @@ static int pci_dev_str_match(struct pci_dev *dev, const char *p,
(!subsystem_vendor ||
subsystem_vendor == dev->subsystem_vendor) &&
(!subsystem_device ||
- subsystem_device == dev->subsystem_device))
- goto found;
+ subsystem_device == dev->subsystem_device)) {
+ ret = 1;
+ goto out;
+ }
+
+ /* No matching string found */
+ ret = 0;
} else {
/*
* PCI Bus, Device, Function IDs are specified
@@ -399,15 +404,18 @@ static int pci_dev_str_match(struct pci_dev *dev, const char *p,
if (ret < 0)
return ret;
else if (ret)
- goto found;
+ goto out;
}
+out:
+ /*
+ * Whether we matched (ret == 1) or didn't (ret == 0),
+ * ensure the token ends with a valid boundary.
+ */
+ if (*p != '\0' && *p != ';' && *p != ',')
+ return -EINVAL;
- *endptr = p;
- return 0;
-
-found:
- *endptr = p;
- return 1;
+ *endptr = *p == '\0' ? p : p + 1;
+ return ret;
}
static u8 __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
@@ -940,12 +948,6 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps,
/* Found a match */
break;
}
-
- if (*p != ';' && *p != ',') {
- /* End of param or invalid format */
- break;
- }
- p++;
}
if (ret != 1)
@@ -6398,12 +6400,6 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev,
p);
break;
}
-
- if (*p != ';' && *p != ',') {
- /* End of param or invalid format */
- break;
- }
- p++;
}
out:
spin_unlock(&resource_alignment_lock);
--
2.51.0