]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
pci: Add checks to prevent config space overflow
authorPali Rohár <pali@kernel.org>
Sun, 3 Jul 2022 10:48:06 +0000 (12:48 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 26 Aug 2022 18:59:21 +0000 (14:59 -0400)
PCIe config space has address range 0-4095. So do not allow reading from
addresses outside of this range. Lot of U-Boot drivers do not expect that
passed value is not in this range. PCI DM read function is extended to
fill read value to all ones or zeros when it fails as U-Boot callers
ignores return value.

Calling U-Boot command 'pci display.b 0.0.0 0 0x2000' now stops printing
config space at the end (before 0x1000 address).

Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Stefan Roese <sr@denx.de>
cmd/pci.c
drivers/pci/pci-uclass.c

index a99e8f8ad6e05b3643b0662410d768ad2d5eb78f..6258699fec81479ae3bf177a24a5d4ebfb1d43ce 100644 (file)
--- a/cmd/pci.c
+++ b/cmd/pci.c
@@ -358,6 +358,9 @@ static int pci_cfg_display(struct udevice *dev, ulong addr,
        if (length == 0)
                length = 0x40 / byte_size; /* Standard PCI config space */
 
+       if (addr >= 4096)
+               return 1;
+
        /* Print the lines.
         * once, and all accesses are with the specified bus width.
         */
@@ -378,7 +381,10 @@ static int pci_cfg_display(struct udevice *dev, ulong addr,
                        rc = 1;
                        break;
                }
-       } while (nbytes > 0);
+       } while (nbytes > 0 && addr < 4096);
+
+       if (rc == 0 && nbytes > 0)
+               return 1;
 
        return (rc);
 }
@@ -390,6 +396,9 @@ static int pci_cfg_modify(struct udevice *dev, ulong addr, ulong size,
        int     nbytes;
        ulong val;
 
+       if (addr >= 4096)
+               return 1;
+
        /* Print the address, followed by value.  Then accept input for
         * the next value.  A non-converted value exits.
         */
@@ -427,7 +436,10 @@ static int pci_cfg_modify(struct udevice *dev, ulong addr, ulong size,
                                        addr += size;
                        }
                }
-       } while (nbytes);
+       } while (nbytes && addr < 4096);
+
+       if (nbytes)
+               return 1;
 
        return 0;
 }
index 2c85e78a13652c6f2a7b8f804c530f31c24d4bd5..16a6a699f922e9599f1b55ecb95929a458ea7660 100644 (file)
@@ -286,6 +286,8 @@ int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset,
        ops = pci_get_ops(bus);
        if (!ops->write_config)
                return -ENOSYS;
+       if (offset < 0 || offset >= 4096)
+               return -EINVAL;
        return ops->write_config(bus, bdf, offset, value, size);
 }
 
@@ -364,8 +366,14 @@ int pci_bus_read_config(const struct udevice *bus, pci_dev_t bdf, int offset,
        struct dm_pci_ops *ops;
 
        ops = pci_get_ops(bus);
-       if (!ops->read_config)
+       if (!ops->read_config) {
+               *valuep = pci_conv_32_to_size(~0, offset, size);
                return -ENOSYS;
+       }
+       if (offset < 0 || offset >= 4096) {
+               *valuep = pci_conv_32_to_size(0, offset, size);
+               return -EINVAL;
+       }
        return ops->read_config(bus, bdf, offset, valuep, size);
 }