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

Configure Feed

Select the types of activity you want to include in your feed.

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 <thomas.weissschuh@linutronix.de>
Link: https://lore.kernel.org/r/20240906-of-address-overflow-v1-1-19567aaa61da@linutronix.de
[robh: Fix to not return error on 0 sized resource]
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>

authored by

Thomas Weißschuh and committed by
Rob Herring (Arm)
1a52a094 22e2bf12

+24 -19
+24 -19
drivers/of/address.c
··· 198 198 199 199 #endif /* CONFIG_PCI */ 200 200 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 + 201 218 /* 202 219 * of_pci_range_to_resource - Create a resource from an of_pci_range 203 220 * @range: the PCI range that describes the resource ··· 233 216 int of_pci_range_to_resource(struct of_pci_range *range, 234 217 struct device_node *np, struct resource *res) 235 218 { 219 + u64 start; 236 220 int err; 237 221 res->flags = range->flags; 238 222 res->parent = res->child = res->sibling = NULL; ··· 250 232 err = -EINVAL; 251 233 goto invalid_range; 252 234 } 253 - res->start = port; 235 + start = port; 254 236 } else { 255 - if ((sizeof(resource_size_t) < 8) && 256 - upper_32_bits(range->cpu_addr)) { 257 - err = -EINVAL; 258 - goto invalid_range; 259 - } 260 - 261 - res->start = range->cpu_addr; 237 + start = range->cpu_addr; 262 238 } 263 - res->end = res->start + range->size - 1; 264 - return 0; 239 + return __of_address_resource_bounds(res, start, range->size); 265 240 266 241 invalid_range: 267 242 res->start = (resource_size_t)OF_BAD_ADDR; ··· 270 259 * @res: pointer to a valid resource that will be updated to 271 260 * reflect the values contained in the range. 272 261 * 273 - * Returns ENOENT if the entry is not found or EINVAL if the range cannot be 274 - * converted to resource. 262 + * Returns -ENOENT if the entry is not found or -EOVERFLOW if the range 263 + * cannot be converted to resource. 275 264 */ 276 265 int of_range_to_resource(struct device_node *np, int index, struct resource *res) 277 266 { ··· 1073 1062 if (of_mmio_is_nonposted(dev)) 1074 1063 flags |= IORESOURCE_MEM_NONPOSTED; 1075 1064 1076 - if (overflows_type(taddr, r->start)) 1077 - return -EOVERFLOW; 1078 - r->start = taddr; 1079 - if (overflows_type(taddr + size - 1, r->end)) 1080 - return -EOVERFLOW; 1081 - r->end = taddr + size - 1; 1082 1065 r->flags = flags; 1083 1066 r->name = name ? name : dev->full_name; 1084 1067 1085 - return 0; 1068 + return __of_address_resource_bounds(r, taddr, size); 1086 1069 } 1087 1070 1088 1071 /**