On Tue, Mar 23, 2021 at 02:04:10PM +1300, Simon Glass wrote: > The root node is supposed to have an empty name, but at present this is > not checked. The behaviour of such a tree is not well defined. Most > software rightly assumes that the root node is at offset 0 and does not > check the name. This oddity was discovered as part of a security > investigation into U-Boot verified boot. > > Add a check for this to fdt_check_full(). > > Signed-off-by: Simon Glass <sjg@xxxxxxxxxxxx> > Reported-by: Arie Haenel <arie.haenel@xxxxxxxxx> > Reported-by: Julien Lenoir <julien.lenoir@xxxxxxxxx> Applied, thanks. > --- > > Changes in v3: > - Add to run_tests.sh also > > Changes in v2: > - Use FDT_ERR_BADSTRUCTURE instead of FDT_ERR_BADLAYOUT > > libfdt/fdt_check.c | 10 ++++++++++ > tests/Makefile.tests | 2 +- > tests/dumptrees.c | 3 ++- > tests/run_tests.sh | 2 +- > tests/testdata.h | 1 + > tests/trees.S | 15 +++++++++++++++ > 6 files changed, 30 insertions(+), 3 deletions(-) > > diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c > index 13595a2..fa410a8 100644 > --- a/libfdt/fdt_check.c > +++ b/libfdt/fdt_check.c > @@ -59,6 +59,16 @@ int fdt_check_full(const void *fdt, size_t bufsize) > depth++; > if (depth > INT_MAX) > return -FDT_ERR_BADSTRUCTURE; > + > + /* The root node must have an empty name */ > + if (depth == 1) { > + const char *name; > + int len; > + > + name = fdt_get_name(fdt, offset, &len); > + if (*name || len) > + return -FDT_ERR_BADSTRUCTURE; > + } > break; > > case FDT_END_NODE: > diff --git a/tests/Makefile.tests b/tests/Makefile.tests > index fe5cae8..2b47627 100644 > --- a/tests/Makefile.tests > +++ b/tests/Makefile.tests > @@ -33,7 +33,7 @@ LIB_TESTS_L = get_mem_rsv \ > LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) > > LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv \ > - two_roots > + two_roots named_root > > LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) > > diff --git a/tests/dumptrees.c b/tests/dumptrees.c > index 02ca092..f1e0ea9 100644 > --- a/tests/dumptrees.c > +++ b/tests/dumptrees.c > @@ -24,7 +24,8 @@ static struct { > TREE(ovf_size_strings), > TREE(truncated_property), TREE(truncated_string), > TREE(truncated_memrsv), > - TREE(two_roots) > + TREE(two_roots), > + TREE(named_root) > }; > > #define NUM_TREES (sizeof(trees) / sizeof(trees[0])) > diff --git a/tests/run_tests.sh b/tests/run_tests.sh > index 82543fc..5c2b1e8 100755 > --- a/tests/run_tests.sh > +++ b/tests/run_tests.sh > @@ -518,7 +518,7 @@ libfdt_tests () { > run_test check_full $good > done > for bad in truncated_property.dtb truncated_string.dtb \ > - truncated_memrsv.dtb two_roots.dtb; do > + truncated_memrsv.dtb two_roots.dtb named_root.dtb; do > run_test check_full -n $bad > done > } > diff --git a/tests/testdata.h b/tests/testdata.h > index d03f352..4f9e3ba 100644 > --- a/tests/testdata.h > +++ b/tests/testdata.h > @@ -56,4 +56,5 @@ extern struct fdt_header ovf_size_strings; > extern struct fdt_header truncated_string; > extern struct fdt_header truncated_memrsv; > extern struct fdt_header two_roots; > +extern struct fdt_header named_root; > #endif /* ! __ASSEMBLY */ > diff --git a/tests/trees.S b/tests/trees.S > index e2380b7..95d599d 100644 > --- a/tests/trees.S > +++ b/tests/trees.S > @@ -298,3 +298,18 @@ two_roots_strings_end: > > two_roots_end: > > + > + /* root node with a non-empty name */ > + TREE_HDR(named_root) > + EMPTY_RSVMAP(named_root) > + > +named_root_struct: > + BEGIN_NODE("fake") > + END_NODE > + FDTLONG(FDT_END) > +named_root_struct_end: > + > +named_root_strings: > +named_root_strings_end: > + > +named_root_end: -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Attachment:
signature.asc
Description: PGP signature