Skip to content

Commit 1a52a09

Browse files
t-8chrobherring
authored andcommitted
of: address: Unify resource bounds overflow checking
The members "start" and "end" of struct resource are of type "resource_size_t" which can be 32bit wide. Values read from OF however are always 64bit wide. Refactor the diff overflow checks into a helper function. Also extend the checks to validate each calculation step. Signed-off-by: Thomas Weißschuh <[email protected]> Link: https://lore.kernel.org/r/[email protected] [robh: Fix to not return error on 0 sized resource] Signed-off-by: Rob Herring (Arm) <[email protected]>
1 parent 22e2bf1 commit 1a52a09

File tree

1 file changed

+24
-19
lines changed

1 file changed

+24
-19
lines changed

drivers/of/address.c

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,23 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
198198

199199
#endif /* CONFIG_PCI */
200200

201+
static int __of_address_resource_bounds(struct resource *r, u64 start, u64 size)
202+
{
203+
u64 end = start;
204+
205+
if (overflows_type(start, r->start))
206+
return -EOVERFLOW;
207+
if (size && check_add_overflow(end, size - 1, &end))
208+
return -EOVERFLOW;
209+
if (overflows_type(end, r->end))
210+
return -EOVERFLOW;
211+
212+
r->start = start;
213+
r->end = end;
214+
215+
return 0;
216+
}
217+
201218
/*
202219
* of_pci_range_to_resource - Create a resource from an of_pci_range
203220
* @range: the PCI range that describes the resource
@@ -216,6 +233,7 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
216233
int of_pci_range_to_resource(struct of_pci_range *range,
217234
struct device_node *np, struct resource *res)
218235
{
236+
u64 start;
219237
int err;
220238
res->flags = range->flags;
221239
res->parent = res->child = res->sibling = NULL;
@@ -232,18 +250,11 @@ int of_pci_range_to_resource(struct of_pci_range *range,
232250
err = -EINVAL;
233251
goto invalid_range;
234252
}
235-
res->start = port;
253+
start = port;
236254
} else {
237-
if ((sizeof(resource_size_t) < 8) &&
238-
upper_32_bits(range->cpu_addr)) {
239-
err = -EINVAL;
240-
goto invalid_range;
241-
}
242-
243-
res->start = range->cpu_addr;
255+
start = range->cpu_addr;
244256
}
245-
res->end = res->start + range->size - 1;
246-
return 0;
257+
return __of_address_resource_bounds(res, start, range->size);
247258

248259
invalid_range:
249260
res->start = (resource_size_t)OF_BAD_ADDR;
@@ -259,8 +270,8 @@ EXPORT_SYMBOL(of_pci_range_to_resource);
259270
* @res: pointer to a valid resource that will be updated to
260271
* reflect the values contained in the range.
261272
*
262-
* Returns ENOENT if the entry is not found or EINVAL if the range cannot be
263-
* converted to resource.
273+
* Returns -ENOENT if the entry is not found or -EOVERFLOW if the range
274+
* cannot be converted to resource.
264275
*/
265276
int of_range_to_resource(struct device_node *np, int index, struct resource *res)
266277
{
@@ -1062,16 +1073,10 @@ static int __of_address_to_resource(struct device_node *dev, int index, int bar_
10621073
if (of_mmio_is_nonposted(dev))
10631074
flags |= IORESOURCE_MEM_NONPOSTED;
10641075

1065-
if (overflows_type(taddr, r->start))
1066-
return -EOVERFLOW;
1067-
r->start = taddr;
1068-
if (overflows_type(taddr + size - 1, r->end))
1069-
return -EOVERFLOW;
1070-
r->end = taddr + size - 1;
10711076
r->flags = flags;
10721077
r->name = name ? name : dev->full_name;
10731078

1074-
return 0;
1079+
return __of_address_resource_bounds(r, taddr, size);
10751080
}
10761081

10771082
/**

0 commit comments

Comments
 (0)