summaryrefslogtreecommitdiffstats
path: root/cpukit/dtc
diff options
context:
space:
mode:
authorTadeusz Struk <tadeusz.struk@linaro.org>2022-10-05 16:29:30 -0700
committerSebastian Huber <sebastian.huber@embedded-brains.de>2022-12-22 08:02:57 +0100
commitb5db3f64e3741a7b572e3416d9827ad663906be9 (patch)
tree4dbbea4440ae912908648f87d85d407cda96a7f6 /cpukit/dtc
parentlibfdt: add fdt_get_property_by_offset_w helper (diff)
downloadrtems-b5db3f64e3741a7b572e3416d9827ad663906be9.tar.bz2
libfdt: prevent integer overflow in fdt_next_tag
Since fdt_next_tag() in a public API function all input parameters, including the fdt blob should not be trusted. It is possible to forge a blob with invalid property length that will cause integer overflow during offset calculation. To prevent that, validate the property length read from the blob before doing calculations. Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org> Message-Id: <20221005232931.3016047-1-tadeusz.struk@linaro.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'cpukit/dtc')
-rw-r--r--cpukit/dtc/libfdt/fdt.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/cpukit/dtc/libfdt/fdt.c b/cpukit/dtc/libfdt/fdt.c
index 90a39e8fb7..20c6415b9c 100644
--- a/cpukit/dtc/libfdt/fdt.c
+++ b/cpukit/dtc/libfdt/fdt.c
@@ -162,7 +162,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const fdt32_t *tagp, *lenp;
- uint32_t tag;
+ uint32_t tag, len, sum;
int offset = startoffset;
const char *p;
@@ -188,12 +188,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
if (!can_assume(VALID_DTB) && !lenp)
return FDT_END; /* premature end */
+
+ len = fdt32_to_cpu(*lenp);
+ sum = len + offset;
+ if (!can_assume(VALID_DTB) &&
+ (INT_MAX <= sum || sum < (uint32_t) offset))
+ return FDT_END; /* premature end */
+
/* skip-name offset, length and value */
- offset += sizeof(struct fdt_property) - FDT_TAGSIZE
- + fdt32_to_cpu(*lenp);
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
+
if (!can_assume(LATEST) &&
- fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
- ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
+ fdt_version(fdt) < 0x10 && len >= 8 &&
+ ((offset - len) % 8) != 0)
offset += 4;
break;