]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[pci] Check that ECAM configuration space is within reachable memory
authorMichael Brown <mcb30@ipxe.org>
Thu, 2 Nov 2023 15:38:08 +0000 (15:38 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 2 Nov 2023 15:38:08 +0000 (15:38 +0000)
Some machines (observed with an AWS EC2 m7a.large instance) will place
the ECAM configuration space window above 4GB, thereby making it
unreachable from non-paged 32-bit code.  This problem is currently
ignored by iPXE, since the address is silently truncated in the call
to ioremap().  (Note that other uses of ioremap() are not affected
since the PCI core will already have checked for unreachable 64-bit
BARs when retrieving the physical address to be mapped.)

Fix by adding an explicit check that the region to be mapped starts
within the reachable memory address space.  (Assume that no machines
will be sufficiently peverse to provide a region that straddles the
4GB boundary.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/bus/ecam.c

index 62baebeedc2b615cccb93f95e54991067276b1f0..5e3debdddc72e70e6cef3a40eece1e9fbe3e3467 100644 (file)
@@ -153,6 +153,14 @@ static int ecam_access ( struct pci_device *pci ) {
        base = le64_to_cpu ( ecam.alloc.base );
        base += ( ecam.alloc.start * ECAM_SIZE * PCI_BUSDEVFN ( 0, 1, 0, 0 ) );
        len = ( ecam.range.count * ECAM_SIZE );
+       if ( base != ( ( unsigned long ) base ) ) {
+               DBGC ( &ecam, "ECAM %04x:[%02x-%02x] could not map "
+                      "[%08llx,%08llx) outside CPU range\n",
+                      le16_to_cpu ( ecam.alloc.segment ), ecam.alloc.start,
+                      ecam.alloc.end, base, ( base + len ) );
+               rc = -ERANGE;
+               goto err_range;
+       }
        ecam.regs = ioremap ( base, len );
        if ( ! ecam.regs ) {
                DBGC ( &ecam, "ECAM %04x:[%02x-%02x] could not map "
@@ -171,6 +179,7 @@ static int ecam_access ( struct pci_device *pci ) {
 
        iounmap ( ecam.regs );
  err_ioremap:
+ err_range:
  err_find:
        ecam.rc = rc;
        return rc;