From c4a17c8dd492b106846abb443c071be65ca6e484 Mon Sep 17 00:00:00 2001 From: vijay kumar Date: Mon, 11 Aug 2014 17:17:59 +0530 Subject: [PATCH] scripts/dtc/libfdt: add integer overflow checks This patch applies the same changes in the original commit below to the dtc to keep both sources in sync. original commit: lib: fdt: add integer overflow checks added integer overflow checks to avoid buffer over reads/write while using the fdt header fields. CRs-fixed: 705078. Change-Id: I062ee9e0610eeeeea32dd95695b18aa9dbca06ea Bug: 19136881 Signed-off-by: Patrick Tjin --- scripts/dtc/libfdt/fdt_rw.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 8e7ec4cb7bcd..05d08d9e834a 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -388,20 +388,31 @@ static void _fdt_packblocks(const char *old, char *new, int fdt_open_into(const void *fdt, void *buf, int bufsize) { - int err; - int mem_rsv_size, struct_size; - int newsize; + int err = -1; + uint32_t mem_rsv_size; + int struct_size; + uint32_t newsize; const char *fdtstart = fdt; - const char *fdtend = fdtstart + fdt_totalsize(fdt); + const char *fdtend = NULL; char *tmp; + if (fdtstart + fdt_totalsize(fdt) < fdtstart) { + return err; + } + fdtend = fdtstart + fdt_totalsize(fdt); FDT_CHECK_HEADER(fdt); + if ((fdt_num_mem_rsv(fdt)+1) > (UINT_MAX / sizeof(struct fdt_reserve_entry))) { + return err; + } + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); if (fdt_version(fdt) >= 17) { struct_size = fdt_size_dt_struct(fdt); + if (struct_size < 0) + return struct_size; } else { struct_size = 0; while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) @@ -418,16 +429,22 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) fdt_set_totalsize(buf, bufsize); return 0; } + if (((uint64_t)FDT_ALIGN(sizeof(struct fdt_header), 8) + (uint64_t)mem_rsv_size \ + + (uint64_t)struct_size + (uint64_t)fdt_size_dt_strings(fdt)) > UINT_MAX) { + return (err = -1); + } /* Need to reorder */ newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + struct_size + fdt_size_dt_strings(fdt); - if (bufsize < newsize) return -FDT_ERR_NOSPACE; /* First attempt to build converted tree at beginning of buffer */ tmp = buf; + if (((tmp + newsize) < tmp) || ((buf + bufsize) < buf)) { + return (err = -1); + } /* But if that overlaps with the old tree... */ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { /* Try right after the old tree instead */