From 882a1262f5379570de5b4f3cc57b6d5730596dd6 Mon Sep 17 00:00:00 2001 From: Babu Moger Date: Mon, 15 Feb 2016 09:42:02 +0100 Subject: [PATCH] PCI: Prevent VPD access for buggy devices On some devices, reading or writing VPD causes a system panic. This can be easily reproduced by running "lspci -vvv" or "cat /sys/bus/devices/XX../vpd". Blacklist these devices so we don't access VPD data at all. [bhelgaas: changelog, comment, drop pci/access.c changes] Link: https://bugzilla.kernel.org/show_bug.cgi?id=110681 Tested-by: Shane Seymour Tested-by: Babu Moger Signed-off-by: Babu Moger Signed-off-by: Hannes Reinecke Signed-off-by: Bjorn Helgaas Cc: Alexander Duyck (cherry picked from commit 7c20078a8197389eead62399419fdc4f8ac4a8a3) Orabug: 25975482 Signed-off-by: Ethan Zhao Reviewed-by: Martin K. Petersen Conflicts: drivers/pci/quirks.c --- drivers/pci/quirks.c | 53 ++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index dca876d4cece0..e600efe3892f2 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2109,42 +2109,33 @@ static void quirk_via_cx700_pci_parking_caching(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching); /* - * A read/write to sysfs entry ('/sys/bus/pci/devices//vpd') - * will dump 32k of data. The default length is set as 32768. - * Reading a full 32k will cause an access beyond the VPD end tag. - * The system behaviour at that point is mostly unpredictable. - * Also I dont believe vendors have implemented this VPD headers properly. - * Atleast I dont see it in following megaraid sas controller. - * That is why adding the quirk here. + * If a device follows the VPD format spec, the PCI core will not read or + * write past the VPD End Tag. But some vendors do not follow the VPD + * format spec, so we can't tell how much data is safe to access. Devices + * may behave unpredictably if we access too much. Blacklist these devices + * so we don't touch VPD at all. */ -static void quirk_megaraid_sas_limit_vpd(struct pci_dev *dev) +static void quirk_blacklist_vpd(struct pci_dev *dev) { - if (dev->vpd) + if (dev->vpd) { dev->vpd->len = 0; + dev_warn(&dev->dev, FW_BUG "VPD access disabled\n"); + } } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0060, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x007c, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0413, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0078, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0079, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0073, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0071, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005b, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x002f, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005d, - quirk_megaraid_sas_limit_vpd); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005f, - quirk_megaraid_sas_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0060, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x007c, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0413, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0078, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0079, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0073, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0071, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005b, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x002f, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005d, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005f, quirk_blacklist_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, PCI_ANY_ID, + quirk_blacklist_vpd); /* * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the -- 2.50.1