git: df3796cc68fc - stable/14 - pci_find_cap_method(): limit number of iterations for finding a capability

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Tue, 14 Jan 2025 08:57:17 UTC
The branch stable/14 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=df3796cc68fc22fc164049ca25c45f646581203a

commit df3796cc68fc22fc164049ca25c45f646581203a
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-01-06 23:29:18 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-01-14 08:56:41 +0000

    pci_find_cap_method(): limit number of iterations for finding a capability
    
    PR:     283815
    
    (cherry picked from commit 6ba2c036a0117ac02f9979b7dc49f15e9c1ea9c9)
---
 sys/dev/pci/pci.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 8236b8bde41a..1a415f676ff7 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1513,6 +1513,7 @@ pci_find_cap_method(device_t dev, device_t child, int capability,
 	pcicfgregs *cfg = &dinfo->cfg;
 	uint32_t status;
 	uint8_t ptr;
+	int cnt;
 
 	/*
 	 * Check the CAP_LIST bit of the PCI status register first.
@@ -1539,9 +1540,11 @@ pci_find_cap_method(device_t dev, device_t child, int capability,
 	ptr = pci_read_config(child, ptr, 1);
 
 	/*
-	 * Traverse the capabilities list.
+	 * Traverse the capabilities list.  Limit by total theoretical
+	 * maximum number of caps: capability needs at least id and
+	 * next registers, and any type X header cannot contain caps.
 	 */
-	while (ptr != 0) {
+	for (cnt = 0; ptr != 0 && cnt < (PCIE_REGMAX - 0x40) / 2; cnt++) {
 		if (pci_read_config(child, ptr + PCICAP_ID, 1) == capability) {
 			if (capreg != NULL)
 				*capreg = ptr;