70166d62a2
fdt_string() is used to retrieve strings from a DT blob's strings section. It's rarely used directly, but is widely used internally. However, it doesn't do any bounds checking, which means in the case of a corrupted blob it could access bad memory, which libfdt is supposed to avoid. This write a safe alternative to fdt_string, fdt_get_string(). It checks both that the given offset is within the string section and that the string it points to is properly \0 terminated within the section. It also returns the string's length as a convenience (since it needs to determine to do the checks anyway). fdt_string() is rewritten in terms of fdt_get_string() for compatibility. Most of the diff here is actually testing infrastructure. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
79 lines
2.6 KiB
C
79 lines
2.6 KiB
C
/*
|
|
* libfdt - Flat Device Tree manipulation
|
|
* Testcase for misbehaviour on a truncated string
|
|
* Copyright (C) 2018 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"
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
void *fdt = &truncated_string;
|
|
const struct fdt_property *good, *bad;
|
|
int off, len;
|
|
const char *name;
|
|
|
|
test_init(argc, argv);
|
|
|
|
off = fdt_first_property_offset(fdt, 0);
|
|
good = fdt_get_property_by_offset(fdt, off, NULL);
|
|
|
|
off = fdt_next_property_offset(fdt, off);
|
|
bad = fdt_get_property_by_offset(fdt, off, NULL);
|
|
|
|
if (fdt32_to_cpu(good->len) != 0)
|
|
FAIL("Unexpected length for good property");
|
|
name = fdt_get_string(fdt, fdt32_to_cpu(good->nameoff), &len);
|
|
if (!name)
|
|
FAIL("fdt_get_string() failed on good property: %s",
|
|
fdt_strerror(len));
|
|
if (len != 4)
|
|
FAIL("fdt_get_string() returned length %d (not 4) on good property",
|
|
len);
|
|
if (!streq(name, "good"))
|
|
FAIL("fdt_get_string() returned \"%s\" (not \"good\") on good property",
|
|
name);
|
|
|
|
if (fdt32_to_cpu(bad->len) != 0)
|
|
FAIL("Unexpected length for bad property\n");
|
|
name = fdt_get_string(fdt, fdt32_to_cpu(bad->nameoff), &len);
|
|
if (name)
|
|
FAIL("fdt_get_string() succeeded incorrectly on bad property");
|
|
else if (len != -FDT_ERR_TRUNCATED)
|
|
FAIL("fdt_get_string() gave unexpected error on bad property: %s",
|
|
fdt_strerror(len));
|
|
|
|
/* Make sure the 'good' property breaks correctly if we
|
|
* truncate the strings section */
|
|
fdt_set_size_dt_strings(fdt, fdt32_to_cpu(good->nameoff) + 4);
|
|
name = fdt_get_string(fdt, fdt32_to_cpu(good->nameoff), &len);
|
|
if (name)
|
|
FAIL("fdt_get_string() succeeded incorrectly on mangled property");
|
|
else if (len != -FDT_ERR_TRUNCATED)
|
|
FAIL("fdt_get_string() gave unexpected error on mangled property: %s",
|
|
fdt_strerror(len));
|
|
|
|
PASS();
|
|
}
|