diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2021-02-03 14:18:27 +0100 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2021-02-05 08:52:58 -0500 |
commit | 7c16b5bbb6c0f797945327d17e4be60f25a4427d (patch) | |
tree | 0e6282cdb510ac438890d0224a814c9f9ec72979 /hw/pci/pci.c | |
parent | 923abdb4bdfb6d93bfe6c941ead70f3ea6707e40 (diff) |
pci: reject too large ROMs
get_image_size() returns an int64_t, which pci_add_option_rom() assigns
to an "int" without any range checking. A 32-bit BAR could be up to
2 GiB in size, so reject anything above it. In order to accomodate
a rounded-up size of 2 GiB, change pci_patch_ids's size argument
to unsigned.
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20210203131828.156467-2-pbonzini@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: David Edmondson <david.edmondson@oracle.com>
Diffstat (limited to 'hw/pci/pci.c')
-rw-r--r-- | hw/pci/pci.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 512e9042ff..58560c044d 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/datadir.h" +#include "qemu/units.h" #include "hw/irq.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" @@ -2234,7 +2235,7 @@ static uint8_t pci_find_capability_at_offset(PCIDevice *pdev, uint8_t offset) /* Patch the PCI vendor and device ids in a PCI rom image if necessary. This is needed for an option rom which is used for more than one device. */ -static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) +static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, uint32_t size) { uint16_t vendor_id; uint16_t device_id; @@ -2292,7 +2293,7 @@ static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, Error **errp) { - int size; + int64_t size; char *path; void *ptr; char name[32]; @@ -2342,6 +2343,11 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, error_setg(errp, "romfile \"%s\" is empty", pdev->romfile); g_free(path); return; + } else if (size > 2 * GiB) { + error_setg(errp, "romfile \"%s\" too large (size cannot exceed 2 GiB)", + pdev->romfile); + g_free(path); + return; } size = pow2ceil(size); |