dtc: fdtdump: check fdt if not in scanning mode

Running fdtdump without scan mode for an invalid file often
results in a segmentation fault because the fdt header is
not checked.

With the patch the header is checked both in scanning as
well as in non-scanning mode.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[dwg: Removed unnecessary inline, changed type from int to bool]
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Heinrich Schuchardt 2016-12-22 00:59:06 +01:00 committed by David Gibson
parent f88865469b
commit 0931cea3ba

View file

@ -16,6 +16,7 @@
#include "util.h" #include "util.h"
#define FDT_MAGIC_SIZE 4 #define FDT_MAGIC_SIZE 4
#define MAX_VERSION 17
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
@ -159,6 +160,20 @@ static const char * const usage_opts_help[] = {
USAGE_COMMON_OPTS_HELP USAGE_COMMON_OPTS_HELP
}; };
static bool valid_header(char *p, off_t len)
{
if (len < sizeof(struct fdt_header) ||
fdt_magic(p) != FDT_MAGIC ||
fdt_version(p) > MAX_VERSION ||
fdt_last_comp_version(p) >= MAX_VERSION ||
fdt_totalsize(p) >= len ||
fdt_off_dt_struct(p) >= len ||
fdt_off_dt_strings(p) >= len)
return 0;
else
return 1;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int opt; int opt;
@ -204,12 +219,7 @@ int main(int argc, char *argv[])
if (fdt_magic(p) == FDT_MAGIC) { if (fdt_magic(p) == FDT_MAGIC) {
/* try and validate the main struct */ /* try and validate the main struct */
off_t this_len = endp - p; off_t this_len = endp - p;
fdt32_t max_version = 17; if (valid_header(p, this_len))
if (fdt_version(p) <= max_version &&
fdt_last_comp_version(p) < max_version &&
fdt_totalsize(p) < this_len &&
fdt_off_dt_struct(p) < this_len &&
fdt_off_dt_strings(p) < this_len)
break; break;
if (debug) if (debug)
printf("%s: skipping fdt magic at offset %#zx\n", printf("%s: skipping fdt magic at offset %#zx\n",
@ -217,11 +227,12 @@ int main(int argc, char *argv[])
} }
++p; ++p;
} }
if (!p || ((endp - p) < FDT_MAGIC_SIZE)) if (!p || endp - p < sizeof(struct fdt_header))
die("%s: could not locate fdt magic\n", file); die("%s: could not locate fdt magic\n", file);
printf("%s: found fdt at offset %#zx\n", file, p - buf); printf("%s: found fdt at offset %#zx\n", file, p - buf);
buf = p; buf = p;
} } else if (!valid_header(buf, len))
die("%s: header is not valid\n", file);
dump_blob(buf, debug); dump_blob(buf, debug);