drivers/staging/vme_user/vme_tsi148.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
In tsi148_crcsr_init() value of vme_base used as 3rd parameter in
tsi148_master_set() call is calculated as 'vstat * 0x80000'. vstat value
can be set from module parameter "geoid" which can be any. In this case
the value of an arithmetic expression 'vstat * 0x80000' is a subject to
overflow because its operands are not cast to a larger data type before
performing arithmetic.
Add geoid validation to prevent overflow.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: d22b8ed9a3b0 ("Staging: vme: add Tundra TSI148 VME-PCI Bridge driver")
Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
---
drivers/staging/vme_user/vme_tsi148.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/vme_user/vme_tsi148.c b/drivers/staging/vme_user/vme_tsi148.c
index 2ec9c2904404..b601d2b20bed 100644
--- a/drivers/staging/vme_user/vme_tsi148.c
+++ b/drivers/staging/vme_user/vme_tsi148.c
@@ -2119,7 +2119,7 @@ static int tsi148_slot_get(struct vme_bridge *tsi148_bridge)
slot = ioread32be(bridge->base + TSI148_LCSR_VSTAT);
slot = slot & TSI148_LCSR_VSTAT_GA_M;
} else {
- slot = geoid;
+ slot = geoid & TSI148_LCSR_VSTAT_GA_M;
}
return (int)slot;
--
2.30.2
On Fri, Jun 21, 2024 at 01:42:46PM +0300, Aleksandr Mishin wrote:
> In tsi148_crcsr_init() value of vme_base used as 3rd parameter in
> tsi148_master_set() call is calculated as 'vstat * 0x80000'. vstat value
> can be set from module parameter "geoid" which can be any. In this case
> the value of an arithmetic expression 'vstat * 0x80000' is a subject to
> overflow because its operands are not cast to a larger data type before
> performing arithmetic.
>
> Add geoid validation to prevent overflow.
>
> Found by Linux Verification Center (linuxtesting.org) with SVACE.
>
> Fixes: d22b8ed9a3b0 ("Staging: vme: add Tundra TSI148 VME-PCI Bridge driver")
> Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
> ---
> drivers/staging/vme_user/vme_tsi148.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/staging/vme_user/vme_tsi148.c b/drivers/staging/vme_user/vme_tsi148.c
> index 2ec9c2904404..b601d2b20bed 100644
> --- a/drivers/staging/vme_user/vme_tsi148.c
> +++ b/drivers/staging/vme_user/vme_tsi148.c
> @@ -2119,7 +2119,7 @@ static int tsi148_slot_get(struct vme_bridge *tsi148_bridge)
> slot = ioread32be(bridge->base + TSI148_LCSR_VSTAT);
> slot = slot & TSI148_LCSR_VSTAT_GA_M;
> } else {
> - slot = geoid;
> + slot = geoid & TSI148_LCSR_VSTAT_GA_M;
geoid is a module parameter. It would be better to add some validation
to the probe() function instead of working around invalid values here.
regards,
dan carpenter
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@linaro.org>
Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
---
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
On Tue, Jun 25, 2024 at 12:58:04PM +0300, Aleksandr Mishin wrote:
> 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@linaro.org>
> Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
> ---
> v1->v2: Move geoid validation to the probe() function as suggested by Dan
Yeah, I think this works.
Reviewed-by: Dan Carpenter <dan.carpenter@linaro.org>
regards,
dan carpenter
© 2016 - 2025 Red Hat, Inc.