On 26/3/18 10:25 am, David Gibson wrote: > This new function implements a complete and thorough check of an fdt blob's > structure. Given a buffer containing an fdt, it should return 0 only if > the fdt within is structurally sound in all regards. It doesn't check > anything about the blob's contents (i.e. the actual values of the nodes and > properties), of course. > > Signed-off-by: David Gibson <david@xxxxxxxxxxxxxxxxxxxxx> > --- > libfdt/fdt_ro.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ > libfdt/libfdt.h | 2 ++ > tests/.gitignore | 1 + > tests/Makefile.tests | 2 +- > tests/check_full.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > tests/dumptrees.c | 2 ++ > tests/run_tests.sh | 9 ++++++++ > 7 files changed, 135 insertions(+), 1 deletion(-) > create mode 100644 tests/check_full.c > > diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c > index c74b962..4dbd0c5 100644 > --- a/libfdt/fdt_ro.c > +++ b/libfdt/fdt_ro.c > @@ -857,3 +857,60 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, > > return offset; /* error from fdt_next_node() */ > } > + > +int fdt_check_full(const void *fdt, size_t bufsize) > +{ > + int err; > + int num_memrsv; > + int offset, nextoffset = 0; > + uint32_t tag; > + unsigned depth = 0; > + > + if (bufsize < FDT_V1_SIZE) > + return -FDT_ERR_TRUNCATED; > + err = fdt_check_header(fdt); > + if (err != 0) > + return err; > + if (bufsize < fdt_totalsize(fdt)) > + return -FDT_ERR_TRUNCATED; > + > + num_memrsv = fdt_num_mem_rsv(fdt); > + if (num_memrsv < 0) > + return num_memrsv; > + > + while (1) { > + offset = nextoffset; > + tag = fdt_next_tag(fdt, offset, &nextoffset); > + > + if (nextoffset < 0) > + return nextoffset; > + > + switch (tag) { > + case FDT_NOP: > + break; > + > + case FDT_END: > + if (depth != 0) > + return -FDT_ERR_BADSTRUCTURE; > + return 0; > + > + case FDT_BEGIN_NODE: > + depth++; > + if (depth > INT_MAX) > + return -FDT_ERR_BADSTRUCTURE; > + break; > + > + case FDT_END_NODE: > + if (depth == 0) > + return -FDT_ERR_BADSTRUCTURE; > + depth--; > + break; > + > + case FDT_PROP: > + break; > + > + default: > + return -FDT_ERR_INTERNAL; > + } > + } > +} > diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h > index 9938fb8..f044298 100644 > --- a/libfdt/libfdt.h > +++ b/libfdt/libfdt.h > @@ -295,6 +295,8 @@ int fdt_move(const void *fdt, void *buf, int bufsize); > /* Read-only functions */ > /**********************************************************************/ > > +int fdt_check_full(const void *fdt, size_t bufsize); > + > /** > * fdt_get_string - retrieve a string from the strings block of a device tree > * @fdt: pointer to the device tree blob > diff --git a/tests/.gitignore b/tests/.gitignore > index 60bbb09..9fce43a 100644 > --- a/tests/.gitignore > +++ b/tests/.gitignore > @@ -8,6 +8,7 @@ tmp.* > /asm_tree_dump > /boot-cpuid > /char_literal > +/check_full > /check_header > /check_path > /del_node > diff --git a/tests/Makefile.tests b/tests/Makefile.tests > index fc1b160..b73a19a 100644 > --- a/tests/Makefile.tests > +++ b/tests/Makefile.tests > @@ -26,7 +26,7 @@ LIB_TESTS_L = get_mem_rsv \ > property_iterate \ > subnode_iterate \ > overlay overlay_bad_fixup \ > - check_path check_header > + check_path check_header check_full > LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) > > LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv > diff --git a/tests/check_full.c b/tests/check_full.c > new file mode 100644 > index 0000000..04c0bc1 > --- /dev/null > +++ b/tests/check_full.c > @@ -0,0 +1,63 @@ > +/* > + * libfdt - Flat Device Tree manipulation > + * Tests if two given dtbs are structurally equal (including order) > + * Copyright (C) 2007 David Gibson, IBM Corporation. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public License > + * as published by the Free Software Foundation; either version 2.1 of > + * the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +#include <stdlib.h> > +#include <stdio.h> > +#include <string.h> > +#include <stdint.h> > + > +#include <libfdt.h> > + > +#include "tests.h" > +#include "testdata.h" > + > +static int expect_bad; /* = 0 */ > + > +int main(int argc, char *argv[]) > +{ > + const char *filename; > + char *fdt; > + size_t len; > + int err; > + > + test_init(argc, argv); > + if ((argc != 2) > + && ((argc != 3) || !streq(argv[1], "-n"))) > + CONFIG("Usage: %s [-n] <dtb file>", argv[0]); > + if (argc == 3) > + expect_bad = 1; > + > + filename = argv[argc-1]; > + err = utilfdt_read_err(filename, &fdt, &len); > + if (err) > + CONFIG("Couldn't open blob from \"%s\": %s", > + filename, strerror(err)); > + > + vg_prepare_blob(fdt, len); > + > + err = fdt_check_full(fdt, len); > + > + if (expect_bad && (err == 0)) > + FAIL("fdt_check_full() succeeded unexpectedly"); check_full -n truncated_string.dtb: FAIL fdt_check_full() succeeded unexpectedly Fails on both ppc64be and x86. > + else if (!expect_bad && (err != 0)) > + FAIL("fdt_check_full() failed: %s", fdt_strerror(err)); > + > + PASS(); > +} > diff --git a/tests/dumptrees.c b/tests/dumptrees.c > index 87d1c3d..ff5818d 100644 > --- a/tests/dumptrees.c > +++ b/tests/dumptrees.c > @@ -37,6 +37,8 @@ static struct { > TREE(test_tree1), > TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char), > TREE(ovf_size_strings), > + TREE(truncated_property), TREE(truncated_string), > + TREE(truncated_memrsv), > }; > > #define NUM_TREES (sizeof(trees) / sizeof(trees[0])) > diff --git a/tests/run_tests.sh b/tests/run_tests.sh > index ee5a43a..615b86d 100755 > --- a/tests/run_tests.sh > +++ b/tests/run_tests.sh > @@ -445,6 +445,15 @@ libfdt_tests () { > > # Check header tests > run_test check_header test_tree1.dtb > + > + # check full tests > + for good in test_tree1.dtb; do > + run_test check_full $good > + done > + for bad in truncated_property.dtb truncated_string.dtb \ > + truncated_memrsv.dtb; do > + run_test check_full -n $bad > + done > } > > dtc_tests () { > -- Alexey -- To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html