diff options
author | Youness Alaoui <kakaroto@kakaroto.homelinux.net> | 2017-07-26 18:03:36 -0400 |
---|---|---|
committer | Nico Huber <nico.h@gmx.de> | 2017-08-10 15:18:11 +0000 |
commit | a54ceb1dbe76e76ca8701dbda3e5baf011b16d6d (patch) | |
tree | f27ce3b104511a8b1598e77858cb42b41cb5e515 /pcidev.c | |
parent | 67d71792929f94d4638a3663f2fc19aea4918681 (diff) | |
download | flashrom-a54ceb1dbe76e76ca8701dbda3e5baf011b16d6d.tar.gz flashrom-a54ceb1dbe76e76ca8701dbda3e5baf011b16d6d.tar.bz2 flashrom-a54ceb1dbe76e76ca8701dbda3e5baf011b16d6d.zip |
rpci: Use pci_dev struct pointer to avoid API breaks
The pci_dev structure is never meant to be used as is, but always as a
pointer. By using the struct itself in undo_pci_write_data, we are risking
data corruption, or buffer overflows if the structure size changes.
This is especially apparent on my system where flashrom segfaults
because I compile it with pciutils 3.3.0 and I run it on a system
with pciutils 3.5.2. The struture size is different and causes a
struct with the wrong size to be sent to the library, with invalid
internal field values.
This has been discovered and discussed in Change ID 18925 [1]
[1] https://review.coreboot.org/#/c/18925/
Change-Id: Icde2e587992ba964d4ff92c33aa659850ba06298
Signed-off-by: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
Reviewed-on: https://review.coreboot.org/20784
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Diffstat (limited to 'pcidev.c')
-rw-r--r-- | pcidev.c | 24 |
1 files changed, 15 insertions, 9 deletions
@@ -160,6 +160,7 @@ static int pcidev_shutdown(void *data) return 1; } pci_cleanup(pacc); + pacc = NULL; return 0; } @@ -259,7 +260,7 @@ enum pci_write_type { }; struct undo_pci_write_data { - struct pci_dev dev; + struct pci_dev *dev; int reg; enum pci_write_type type; union { @@ -272,22 +273,23 @@ struct undo_pci_write_data { int undo_pci_write(void *p) { struct undo_pci_write_data *data = p; - if (pacc == NULL) { - msg_perr("%s: Tried to undo PCI writes without a valid PCI context!\n" - "Please report a bug at flashrom@flashrom.org\n", __func__); + if (pacc == NULL || data->dev == NULL) { + msg_perr("%s: Tried to undo PCI writes without a valid PCI %s!\n" + "Please report a bug at flashrom@flashrom.org\n", + __func__, data->dev == NULL ? "device" : "context"); return 1; } msg_pdbg("Restoring PCI config space for %02x:%02x:%01x reg 0x%02x\n", - data->dev.bus, data->dev.dev, data->dev.func, data->reg); + data->dev->bus, data->dev->dev, data->dev->func, data->reg); switch (data->type) { case pci_write_type_byte: - pci_write_byte(&data->dev, data->reg, data->bytedata); + pci_write_byte(data->dev, data->reg, data->bytedata); break; case pci_write_type_word: - pci_write_word(&data->dev, data->reg, data->worddata); + pci_write_word(data->dev, data->reg, data->worddata); break; case pci_write_type_long: - pci_write_long(&data->dev, data->reg, data->longdata); + pci_write_long(data->dev, data->reg, data->longdata); break; } /* p was allocated in register_undo_pci_write. */ @@ -303,7 +305,11 @@ int undo_pci_write(void *p) msg_gerr("Out of memory!\n"); \ exit(1); \ } \ - undo_pci_write_data->dev = *a; \ + if (pacc) \ + undo_pci_write_data->dev = pci_get_dev(pacc, \ + a->domain, a->bus, a->dev, a->func); \ + else \ + undo_pci_write_data->dev = NULL; \ undo_pci_write_data->reg = b; \ undo_pci_write_data->type = pci_write_type_##c; \ undo_pci_write_data->c##data = pci_read_##c(dev, reg); \ |