The address of VME window is either set by jumpers (VME64) or derived from the slot number (geographical addressing, VME64x) with the formula: address = slot# * 0x80000 https://indico.cern.ch/event/68278/contributions/1234555/attachments/ 1024465/1458672/VMEbus.pdf slot# value can be set from module parameter 'geoid' which can contain any value. In this case the value of an arithmetic expression 'slot# * 0x80000' is a subject to overflow because its operands are not cast to a larger data type before performing arithmetic. Validate the provided geoid value using the Geographic Addr Mask. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: d22b8ed9a3b0 ("Staging: vme: add Tundra TSI148 VME-PCI Bridge driver") Suggested-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx> Signed-off-by: Aleksandr Mishin <amishin@xxxxxxxxxx> --- v1->v2: Move geoid validation to the probe() function as suggested by Dan drivers/staging/vme_user/vme_tsi148.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vme_user/vme_tsi148.c b/drivers/staging/vme_user/vme_tsi148.c index 2ec9c2904404..e7fcbc3f4348 100644 --- a/drivers/staging/vme_user/vme_tsi148.c +++ b/drivers/staging/vme_user/vme_tsi148.c @@ -2448,12 +2448,17 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); dev_info(&pdev->dev, "Board is%s the VME system controller\n", (data & TSI148_LCSR_VSTAT_SCONS) ? "" : " not"); - if (!geoid) + if (!geoid) { dev_info(&pdev->dev, "VME geographical address is %d\n", data & TSI148_LCSR_VSTAT_GA_M); - else + } else if (geoid & ~TSI148_LCSR_VSTAT_GA_M) { + dev_err(&pdev->dev, "VME geographical address is out of range\n"); + retval = -EINVAL; + goto err_crcsr; + } else { dev_info(&pdev->dev, "VME geographical address is set to %d\n", geoid); + } dev_info(&pdev->dev, "VME Write and flush and error check is %s\n", err_chk ? "enabled" : "disabled"); -- 2.30.2