Catch unsigned 32bit overflow when parsing flattened device tree offsets
We have a couple of checks of the form: if (offset+size > totalsize) die(); We need to check that offset+size doesn't overflow, otherwise the check will pass, and we may access past totalsize. Found with AFL. Signed-off-by: Anton Blanchard <anton@samba.org> [Added a testcase] Signed-off-by: David Gibson <david@gibson.dropbear.id.au>main
parent
b06e55c88b
commit
2e53f9d2f0
|
@ -889,7 +889,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
||||||
|
|
||||||
if (version >= 3) {
|
if (version >= 3) {
|
||||||
uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
|
uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
|
||||||
if (off_str+size_str > totalsize)
|
if ((off_str+size_str < off_str) || (off_str+size_str > totalsize))
|
||||||
die("String table extends past total size\n");
|
die("String table extends past total size\n");
|
||||||
inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
|
inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
|
||||||
} else {
|
} else {
|
||||||
|
@ -898,7 +898,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
||||||
|
|
||||||
if (version >= 17) {
|
if (version >= 17) {
|
||||||
size_dt = fdt32_to_cpu(fdt->size_dt_struct);
|
size_dt = fdt32_to_cpu(fdt->size_dt_struct);
|
||||||
if (off_dt+size_dt > totalsize)
|
if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize))
|
||||||
die("Structure block extends past total size\n");
|
die("Structure block extends past total size\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct {
|
||||||
#define TREE(name) { &_##name, #name ".dtb" }
|
#define TREE(name) { &_##name, #name ".dtb" }
|
||||||
TREE(test_tree1),
|
TREE(test_tree1),
|
||||||
TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char),
|
TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char),
|
||||||
|
TREE(ovf_size_strings),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
|
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
|
||||||
|
|
|
@ -295,6 +295,8 @@ libfdt_tests () {
|
||||||
run_dtc_test -I dts -O dtb nul-in-escape.dts
|
run_dtc_test -I dts -O dtb nul-in-escape.dts
|
||||||
run_wrap_error_test $DTC nul-in-line-info1.dts
|
run_wrap_error_test $DTC nul-in-line-info1.dts
|
||||||
run_wrap_error_test $DTC nul-in-line-info2.dts
|
run_wrap_error_test $DTC nul-in-line-info2.dts
|
||||||
|
|
||||||
|
run_wrap_error_test $DTC -I dtb -O dts -o /dev/null ovf_size_strings.dtb
|
||||||
}
|
}
|
||||||
|
|
||||||
dtc_tests () {
|
dtc_tests () {
|
||||||
|
|
|
@ -33,4 +33,5 @@ extern struct fdt_header _truncated_property;
|
||||||
extern struct fdt_header _bad_node_char;
|
extern struct fdt_header _bad_node_char;
|
||||||
extern struct fdt_header _bad_node_format;
|
extern struct fdt_header _bad_node_format;
|
||||||
extern struct fdt_header _bad_prop_char;
|
extern struct fdt_header _bad_prop_char;
|
||||||
|
extern struct fdt_header _ovf_size_strings;
|
||||||
#endif /* ! __ASSEMBLY */
|
#endif /* ! __ASSEMBLY */
|
||||||
|
|
|
@ -209,3 +209,34 @@ bad_prop_char_strings:
|
||||||
STRING(bad_prop_char, prop, "prop$erty")
|
STRING(bad_prop_char, prop, "prop$erty")
|
||||||
bad_prop_char_strings_end:
|
bad_prop_char_strings_end:
|
||||||
bad_prop_char_end:
|
bad_prop_char_end:
|
||||||
|
|
||||||
|
|
||||||
|
/* overflow_size_strings */
|
||||||
|
.balign 8
|
||||||
|
.globl _ovf_size_strings
|
||||||
|
_ovf_size_strings:
|
||||||
|
ovf_size_strings:
|
||||||
|
FDTLONG(FDT_MAGIC)
|
||||||
|
FDTLONG(ovf_size_strings_end - ovf_size_strings)
|
||||||
|
FDTLONG(ovf_size_strings_struct - ovf_size_strings)
|
||||||
|
FDTLONG(ovf_size_strings_strings - ovf_size_strings)
|
||||||
|
FDTLONG(ovf_size_strings_rsvmap - ovf_size_strings)
|
||||||
|
FDTLONG(0x11)
|
||||||
|
FDTLONG(0x10)
|
||||||
|
FDTLONG(0)
|
||||||
|
FDTLONG(0xffffffff)
|
||||||
|
FDTLONG(ovf_size_strings_struct_end - ovf_size_strings_struct)
|
||||||
|
EMPTY_RSVMAP(ovf_size_strings)
|
||||||
|
|
||||||
|
ovf_size_strings_struct:
|
||||||
|
BEGIN_NODE("")
|
||||||
|
PROP_INT(ovf_size_strings, bad_string, 0)
|
||||||
|
END_NODE
|
||||||
|
FDTLONG(FDT_END)
|
||||||
|
ovf_size_strings_struct_end:
|
||||||
|
|
||||||
|
ovf_size_strings_strings:
|
||||||
|
STRING(ovf_size_strings, x, "x")
|
||||||
|
ovf_size_strings_bad_string = ovf_size_strings_strings + 0x10000000
|
||||||
|
ovf_size_strings_strings_end:
|
||||||
|
ovf_size_strings_end:
|
||||||
|
|
Loading…
Reference in New Issue