Browse Source

libfdt: Fix bounds-checking bug in fdt_get_property()

The libfdt functions are supposed to behave tolerably well when practical,
even if given a corrupted device tree as input.  A silly mistake in
fdt_get_property() means we're bounds checking against the size of a pointer
instead of the size of a property header, meaning we can get bogus
behaviour in a corrupted device tree where the structure block ends in
what's supposed to be the middle of a property.

This patch corrects the problem (fdt_get_property() will now return
BADSTRUCTURE in this case), and also adds a testcase to catch the bug.
main
David Gibson 18 years ago
parent
commit
9825f823eb
  1. 2
      fdt_ro.c
  2. 5
      tests/Makefile
  3. 3
      tests/run_tests.sh
  4. 1
      tests/testdata.h
  5. 14
      tests/trees.S
  6. 49
      tests/truncated_property.c

2
fdt_ro.c

@ -193,7 +193,7 @@ struct fdt_property *fdt_get_property(const struct fdt_header *fdt, @@ -193,7 +193,7 @@ struct fdt_property *fdt_get_property(const struct fdt_header *fdt,
/* Found it! */
int len = fdt32_to_cpu(prop->len);
prop = fdt_offset_ptr(fdt, offset,
sizeof(prop)+len);
sizeof(*prop)+len);
if (! prop)
return PTR_ERROR(FDT_ERR_BADSTRUCTURE);


5
tests/Makefile

@ -6,7 +6,8 @@ LIB_TESTS = root_node find_property subnode_offset path_offset getprop \ @@ -6,7 +6,8 @@ LIB_TESTS = root_node find_property subnode_offset path_offset getprop \
sw_tree1 \
move_and_save \
open_pack rw_tree1 setprop del_property del_node
TESTS = $(LIB_TESTS)
LIBTREE_TESTS = truncated_property
TESTS = $(LIB_TESTS) $(LIBTREE_TESTS)
UTILS = dumptrees

TREES = test_tree1.dtb
@ -42,6 +43,8 @@ all: $(TESTS) $(TREES) @@ -42,6 +43,8 @@ all: $(TESTS) $(TREES)

$(LIB_TESTS): %: testutils.o $(LIBFDT)

$(LIBTREE_TESTS): %: testutils.o trees.o $(LIBFDT)

dumptrees: %: trees.o

$(TREES): dumptrees

3
tests/run_tests.sh

@ -58,6 +58,9 @@ functional_tests () { @@ -58,6 +58,9 @@ functional_tests () {
run_test del_node test_tree1.dtb
run_test rw_tree1
tree1_tests rw_tree1.test.dtb

# Tests for behaviour on various sorts of corrupted trees
run_test truncated_property
}

stress_tests () {

1
tests/testdata.h

@ -5,4 +5,5 @@ @@ -5,4 +5,5 @@

#ifndef __ASSEMBLY__
extern struct fdt_header _test_tree1;
extern struct fdt_header _truncated_property;
#endif /* ! __ASSEMBLY */

14
tests/trees.S

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
.byte (val) & 0xff

#define TREE_HDR(tree) \
.balign 4 ; \
.globl _##tree ; \
_##tree: \
tree: \
@ -100,3 +101,16 @@ test_tree1_strings: @@ -100,3 +101,16 @@ test_tree1_strings:
STRING(test_tree1, prop_int, "prop-int")
STRING(test_tree1, prop_str, "prop-str")
test_tree1_end:

TREE_HDR(truncated_property)
truncated_property_rsvmap:
RSVMAP_ENTRY(0, 0)

truncated_property_struct:
BEGIN_NODE("")
PROPHDR(truncated_property, prop_truncated, 4)
/* Oops, no actual property data here */
truncated_property_strings:
STRING(truncated_property, prop_truncated, "truncated")
truncated_property_end:

49
tests/truncated_property.c

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
/*
* libfdt - Flat Device Tree manipulation
* Testcase for misbehaviour on a truncated property
* Copyright (C) 2006 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 <fdt.h>
#include <libfdt.h>

#include "tests.h"
#include "testdata.h"

int main(int argc, char *argv[])
{
void *fdt = &_truncated_property;
void *prop;
int err;
int len;

test_init(argc, argv);

prop = fdt_getprop(fdt, 0, "truncated", &len);
err = fdt_ptr_error(prop);
if (! err)
FAIL("fdt_getprop() succeeded on truncated property");
if (err != FDT_ERR_BADSTRUCTURE)
FAIL("fdt_getprop() failed with \"%s\" instead of \"%s\"",
fdt_strerror(err), fdt_strerror(FDT_ERR_BADSTRUCTURE));

PASS();
}
Loading…
Cancel
Save