Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xen-pciback: reject out of range inputs

This add checks for out of range numbers (including in cases where the
folding of slot and function into a single value could yield false
matches).

It also removes the bogus field width restrictions in str_to_quirk() -
nowhere else in the driver this is being done, and hence this function
could reject input the equivalent of which would be happily accepted
in other places (in particular, "0x" prefixes causing the effective
width of the actual number to be either zero or less than what would be
required to cover the full range of valid values). Note that for the
moment this second part is cosmetic only, as the kernel's sscanf()
currently ignores the field widths, but a patch to overcome this is on
its way.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

authored by

Jan Beulich and committed by
Konrad Rzeszutek Wilk
b3e40b72 5b71fbdc

+27 -12
+27 -12
drivers/xen/xen-pciback/pci_stub.c
··· 142 142 if (psdev->dev != NULL 143 143 && domain == pci_domain_nr(psdev->dev->bus) 144 144 && bus == psdev->dev->bus->number 145 - && PCI_DEVFN(slot, func) == psdev->dev->devfn) { 145 + && slot == PCI_SLOT(psdev->dev->devfn) 146 + && func == PCI_FUNC(psdev->dev->devfn)) { 146 147 pcistub_device_get(psdev); 147 148 goto out; 148 149 } ··· 192 191 if (psdev->dev != NULL 193 192 && domain == pci_domain_nr(psdev->dev->bus) 194 193 && bus == psdev->dev->bus->number 195 - && PCI_DEVFN(slot, func) == psdev->dev->devfn) { 194 + && slot == PCI_SLOT(psdev->dev->devfn) 195 + && func == PCI_FUNC(psdev->dev->devfn)) { 196 196 found_dev = pcistub_device_get_pci_dev(pdev, psdev); 197 197 break; 198 198 } ··· 938 936 { 939 937 int parsed = 0; 940 938 941 - sscanf(buf, " %4x:%2x:%2x.%d-%8x:%1x:%8x %n", domain, bus, slot, func, 939 + sscanf(buf, " %x:%x:%x.%x-%x:%x:%x %n", domain, bus, slot, func, 942 940 reg, size, mask, &parsed); 943 941 if (parsed && !buf[parsed]) 944 942 return 0; 945 943 946 944 /* try again without domain */ 947 945 *domain = 0; 948 - sscanf(buf, " %2x:%2x.%d-%8x:%1x:%8x %n", bus, slot, func, reg, size, 946 + sscanf(buf, " %x:%x.%x-%x:%x:%x %n", bus, slot, func, reg, size, 949 947 mask, &parsed); 950 948 if (parsed && !buf[parsed]) 951 949 return 0; ··· 957 955 { 958 956 struct pcistub_device_id *pci_dev_id; 959 957 unsigned long flags; 960 - int rc = 0; 958 + int rc = 0, devfn = PCI_DEVFN(slot, func); 961 959 962 960 if (slot < 0) { 963 961 for (slot = 0; !rc && slot < 32; ++slot) ··· 971 969 return rc; 972 970 } 973 971 972 + if (( 973 + #if !defined(MODULE) /* pci_domains_supported is not being exported */ \ 974 + || !defined(CONFIG_PCI_DOMAINS) 975 + !pci_domains_supported ? domain : 976 + #endif 977 + domain < 0 || domain > 0xffff) 978 + || bus < 0 || bus > 0xff 979 + || PCI_SLOT(devfn) != slot 980 + || PCI_FUNC(devfn) != func) 981 + return -EINVAL; 982 + 974 983 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); 975 984 if (!pci_dev_id) 976 985 return -ENOMEM; 977 986 978 987 pci_dev_id->domain = domain; 979 988 pci_dev_id->bus = bus; 980 - pci_dev_id->devfn = PCI_DEVFN(slot, func); 989 + pci_dev_id->devfn = devfn; 981 990 982 991 pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n", 983 992 domain, bus, slot, func); ··· 1029 1016 return err; 1030 1017 } 1031 1018 1032 - static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, 1033 - int size, int mask) 1019 + static int pcistub_reg_add(int domain, int bus, int slot, int func, 1020 + unsigned int reg, unsigned int size, 1021 + unsigned int mask) 1034 1022 { 1035 1023 int err = 0; 1036 1024 struct pcistub_device *psdev; 1037 1025 struct pci_dev *dev; 1038 1026 struct config_field *field; 1027 + 1028 + if (reg > 0xfff || (size < 4 && (mask >> (size * 8)))) 1029 + return -EINVAL; 1039 1030 1040 1031 psdev = pcistub_device_find(domain, bus, slot, func); 1041 1032 if (!psdev) { ··· 1271 1254 int err; 1272 1255 struct pcistub_device *psdev; 1273 1256 struct xen_pcibk_dev_data *dev_data; 1257 + 1274 1258 err = str_to_slot(buf, &domain, &bus, &slot, &func); 1275 1259 if (err) 1276 1260 goto out; 1277 - if (slot < 0 || func < 0) { 1278 - err = -EINVAL; 1279 - goto out; 1280 - } 1261 + 1281 1262 psdev = pcistub_device_find(domain, bus, slot, func); 1282 1263 if (!psdev) { 1283 1264 err = -ENODEV;