]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[pci] Check for wraparound in callers of pci_find_next()
authorMichael Brown <mcb30@ipxe.org>
Thu, 15 Sep 2022 14:04:01 +0000 (15:04 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 15 Sep 2022 14:20:58 +0000 (15:20 +0100)
The semantics of the bus:dev.fn parameter passed to pci_find_next()
are "find the first existent PCI device at this address or higher",
with the caller expected to increment the address between finding
devices.  This does not allow the parameter to distinguish between the
two cases "start from address zero" and "wrapped after incrementing
maximal possible address", which could therefore lead to an infinite
loop in the degenerate case that a device with address ffff:ff:1f.7
really exists.

Fix by checking for wraparound in the caller (which is already
responsible for performing the increment).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/bus/pci.c
src/hci/commands/pci_cmd.c
src/include/ipxe/errfile.h

index 60d5df1125bd036eb60ef94538728441dcb35060..c5deb08f618863bc8b21fc6442ac8925500559cd 100644 (file)
@@ -352,8 +352,7 @@ static int pcibus_probe ( struct root_device *rootdev ) {
        uint32_t busdevfn = 0;
        int rc;
 
-       for ( busdevfn = 0 ; 1 ; busdevfn++ ) {
-
+       do {
                /* Allocate struct pci_device */
                if ( ! pci )
                        pci = malloc ( sizeof ( *pci ) );
@@ -386,7 +385,8 @@ static int pcibus_probe ( struct root_device *rootdev ) {
                        /* Not registered; re-use struct pci_device */
                        list_del ( &pci->dev.siblings );
                }
-       }
+
+       } while ( ++busdevfn );
 
        free ( pci );
        return 0;
index 515798baf1228eb6c9669bf02e39dc659c84242d..5bae66fbeebe83087a2e86e0c5f538a20db88e47 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <stdio.h>
+#include <errno.h>
 #include <getopt.h>
 #include <ipxe/pci.h>
 #include <ipxe/command.h>
@@ -79,6 +80,10 @@ static int pciscan_exec ( int argc, char **argv ) {
        } else {
                /* Setting is defined: start searching from next location */
                busdevfn = ( prev + 1 );
+               if ( ! busdevfn ) {
+                       rc = -ENOENT;
+                       goto err_end;
+               }
        }
 
        /* Find next existent PCI device */
@@ -101,6 +106,7 @@ static int pciscan_exec ( int argc, char **argv ) {
        }
 
  err_store:
+ err_end:
  err_find_next:
  err_parse_setting:
  err_parse_options:
index 359e4d2cef673895afb8dbf847c88eb1885493eb..9b955e574905c3df8f5344b15d4396b42272b8d4 100644 (file)
@@ -397,6 +397,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #define ERRFILE_linux_sysfs          ( ERRFILE_OTHER | 0x00560000 )
 #define ERRFILE_linux_acpi           ( ERRFILE_OTHER | 0x00570000 )
 #define ERRFILE_dynkeymap            ( ERRFILE_OTHER | 0x00580000 )
+#define ERRFILE_pci_cmd                      ( ERRFILE_OTHER | 0x00590000 )
 
 /** @} */