Browse Source

tests: Use valgrind client requests for better checking

libfdt is never supposed to access memory outside the the blob, or outside
the sub-blocks within it, even if the blob is badly corrupted.

We can leverage valgrind's client requests to do better testing of this.
This adds a vg_prepare_blob() function which marks just the valid parts of
an fdt blob as properly initialized, explicitly marking the rest as
uninitialized.  This means valgrind should catch any bad accesses.

We add a call to vg_prepare_blob() to load_blob() so that lots of the
existing testcases will benefit from the extra checking.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
main
David Gibson 7 years ago
parent
commit
c14223fb22
  1. 1
      .travis.yml
  2. 1
      tests/tests.h
  3. 55
      tests/testutils.c
  4. 2
      tests/truncated_property.c
  5. 2
      tests/truncated_string.c

1
.travis.yml

@ -29,6 +29,7 @@ matrix: @@ -29,6 +29,7 @@ matrix:
- addons:
apt:
packages:
- valgrind
script:
- make
- make check

1
tests/tests.h

@ -119,6 +119,7 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name, @@ -119,6 +119,7 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name,
#define check_getprop_string(fdt, nodeoffset, name, s) \
check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s))
int nodename_eq(const char *s1, const char *s2);
void vg_prepare_blob(void *fdt, size_t bufsize);
void *load_blob(const char *filename);
void *load_blob_arg(int argc, char *argv[]);
void save_blob(const char *filename, void *blob);

55
tests/testutils.c

@ -36,6 +36,9 @@ @@ -36,6 +36,9 @@

#include "tests.h"

/* For FDT_SW_MAGIC */
#include "libfdt_internal.h"

int verbose_test = 1;
char *test_name;

@ -161,14 +164,64 @@ int nodename_eq(const char *s1, const char *s2) @@ -161,14 +164,64 @@ int nodename_eq(const char *s1, const char *s2)
return 0;
}

void vg_prepare_blob(void *fdt, size_t bufsize)
{
char *blob = fdt;
int off_memrsv, off_strings, off_struct;
size_t size_memrsv, size_strings, size_struct;

size_memrsv = (fdt_num_mem_rsv(fdt) + 1)
* sizeof(struct fdt_reserve_entry);

VALGRIND_MAKE_MEM_UNDEFINED(blob, bufsize);
VALGRIND_MAKE_MEM_DEFINED(blob, FDT_V1_SIZE);
VALGRIND_MAKE_MEM_DEFINED(blob, fdt_header_size(fdt));

if (fdt_magic(fdt) == FDT_MAGIC) {
off_memrsv = fdt_off_mem_rsvmap(fdt);

off_strings = fdt_off_dt_strings(fdt);
if (fdt_version(fdt) >= 3)
size_strings = fdt_size_dt_strings(fdt);
else
size_strings = fdt_totalsize(fdt) - off_strings;

off_struct = fdt_off_dt_struct(fdt);
if (fdt_version(fdt) >= 17)
size_struct = fdt_size_dt_struct(fdt);
else
size_struct = fdt_totalsize(fdt) - off_struct;
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
off_memrsv = fdt_off_mem_rsvmap(fdt);

size_strings = fdt_size_dt_strings(fdt);
off_strings = fdt_off_dt_strings(fdt) - size_strings;

off_struct = fdt_off_dt_struct(fdt);
size_struct = fdt_size_dt_struct(fdt);
size_struct = fdt_totalsize(fdt) - off_struct;

} else {
CONFIG("Bad magic on vg_prepare_blob()");
}

VALGRIND_MAKE_MEM_DEFINED(blob + off_memrsv, size_memrsv);
VALGRIND_MAKE_MEM_DEFINED(blob + off_strings, size_strings);
VALGRIND_MAKE_MEM_DEFINED(blob + off_struct, size_struct);
}

void *load_blob(const char *filename)
{
char *blob;
int ret = utilfdt_read_err(filename, &blob, NULL);
size_t len;
int ret = utilfdt_read_err(filename, &blob, &len);

if (ret)
CONFIG("Couldn't open blob from \"%s\": %s", filename,
strerror(ret));

vg_prepare_blob(blob, len);

return blob;
}


2
tests/truncated_property.c

@ -36,6 +36,8 @@ int main(int argc, char *argv[]) @@ -36,6 +36,8 @@ int main(int argc, char *argv[])

test_init(argc, argv);

vg_prepare_blob(fdt, fdt_totalsize(fdt));

prop = fdt_getprop(fdt, 0, "truncated", &len);
if (prop)
FAIL("fdt_getprop() succeeded on truncated property");

2
tests/truncated_string.c

@ -37,6 +37,8 @@ int main(int argc, char *argv[]) @@ -37,6 +37,8 @@ int main(int argc, char *argv[])

test_init(argc, argv);

vg_prepare_blob(fdt, fdt_totalsize(fdt));

off = fdt_first_property_offset(fdt, 0);
good = fdt_get_property_by_offset(fdt, off, NULL);


Loading…
Cancel
Save