mirror of
https://github.com/dgibson/dtc.git
synced 2026-05-12 11:43:04 -04:00
libfdt: Fix bugs with unchecked usage of fdt_num_mem_rsv()
Some checks failed
Build test / build-make (alpine) (push) Has been cancelled
Build test / build-make (archlinux) (push) Has been cancelled
Build test / build-make (fedora) (push) Has been cancelled
Build test / build-make (ubuntu) (push) Has been cancelled
Build test / build-meson (alpine) (push) Has been cancelled
Build test / build-meson (archlinux) (push) Has been cancelled
Build test / build-meson (fedora) (push) Has been cancelled
Build test / build-meson (ubuntu) (push) Has been cancelled
Build test / clang64 (push) Has been cancelled
Build test / mingw32 (push) Has been cancelled
Build test / mingw64 (push) Has been cancelled
Build test / ucrt64 (push) Has been cancelled
Some checks failed
Build test / build-make (alpine) (push) Has been cancelled
Build test / build-make (archlinux) (push) Has been cancelled
Build test / build-make (fedora) (push) Has been cancelled
Build test / build-make (ubuntu) (push) Has been cancelled
Build test / build-meson (alpine) (push) Has been cancelled
Build test / build-meson (archlinux) (push) Has been cancelled
Build test / build-meson (fedora) (push) Has been cancelled
Build test / build-meson (ubuntu) (push) Has been cancelled
Build test / clang64 (push) Has been cancelled
Build test / mingw32 (push) Has been cancelled
Build test / mingw64 (push) Has been cancelled
Build test / ucrt64 (push) Has been cancelled
fdt_num_mem_rsv() can return an error if the memory reservation block is not properly terminated with a (0, 0) entry. However several other places in libfdt called it without checking for error returns, and could therefore return strange results, or in the case of fdt_open_into() crash. Fix this by always checking the return value. Add some addition tests to catch this bug. Reported-by: Moshe Strauss <moshestrauss10@gmail.com> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
f551be7b39
commit
47d7c01ba8
11 changed files with 127 additions and 9 deletions
|
|
@ -191,6 +191,8 @@ int fdt_num_mem_rsv(const void *fdt)
|
||||||
int i;
|
int i;
|
||||||
const struct fdt_reserve_entry *re;
|
const struct fdt_reserve_entry *re;
|
||||||
|
|
||||||
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
|
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
|
||||||
if (fdt64_ld_(&re->size) == 0)
|
if (fdt64_ld_(&re->size) == 0)
|
||||||
return i;
|
return i;
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,11 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
|
||||||
|
|
||||||
FDT_RW_PROBE(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
|
err = fdt_num_mem_rsv(fdt);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
re = fdt_mem_rsv_w_(fdt, err);
|
||||||
err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
|
err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -179,10 +183,15 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
|
||||||
int fdt_del_mem_rsv(void *fdt, int n)
|
int fdt_del_mem_rsv(void *fdt, int n)
|
||||||
{
|
{
|
||||||
struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
|
struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
|
||||||
|
int num;
|
||||||
|
|
||||||
FDT_RW_PROBE(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
if (n >= fdt_num_mem_rsv(fdt))
|
num = fdt_num_mem_rsv(fdt);
|
||||||
|
if (num < 0)
|
||||||
|
return num;
|
||||||
|
|
||||||
|
if (n >= num)
|
||||||
return -FDT_ERR_NOTFOUND;
|
return -FDT_ERR_NOTFOUND;
|
||||||
|
|
||||||
return fdt_splice_mem_rsv_(fdt, re, 1, 0);
|
return fdt_splice_mem_rsv_(fdt, re, 1, 0);
|
||||||
|
|
@ -439,8 +448,10 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
||||||
|
|
||||||
FDT_RO_PROBE(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
err = fdt_num_mem_rsv(fdt);
|
||||||
* sizeof(struct fdt_reserve_entry);
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
mem_rsv_size = (err + 1) * sizeof(struct fdt_reserve_entry);
|
||||||
|
|
||||||
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
|
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
|
||||||
struct_size = fdt_size_dt_struct(fdt);
|
struct_size = fdt_size_dt_struct(fdt);
|
||||||
|
|
@ -498,12 +509,14 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
||||||
|
|
||||||
int fdt_pack(void *fdt)
|
int fdt_pack(void *fdt)
|
||||||
{
|
{
|
||||||
int mem_rsv_size;
|
int err, mem_rsv_size;
|
||||||
|
|
||||||
FDT_RW_PROBE(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
err = fdt_num_mem_rsv(fdt);
|
||||||
* sizeof(struct fdt_reserve_entry);
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
mem_rsv_size = (err+1) * sizeof(struct fdt_reserve_entry);
|
||||||
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
|
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
|
||||||
fdt_size_dt_strings(fdt));
|
fdt_size_dt_strings(fdt));
|
||||||
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
|
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
|
||||||
|
|
|
||||||
|
|
@ -475,7 +475,12 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
|
||||||
* or any other (0,0) entries reserved for expansion.
|
* or any other (0,0) entries reserved for expansion.
|
||||||
*
|
*
|
||||||
* returns:
|
* returns:
|
||||||
* the number of entries
|
* the number of entries, on success
|
||||||
|
* -FDT_ERR_ALIGNMENT,
|
||||||
|
* -FDT_ERR_BADMAGIC,
|
||||||
|
* -FDT_ERR_BADVERSION,
|
||||||
|
* -FDT_ERR_BADSTATE,
|
||||||
|
* -FDT_ERR_TRUNCATED, standard meanings
|
||||||
*/
|
*/
|
||||||
int fdt_num_mem_rsv(const void *fdt);
|
int fdt_num_mem_rsv(const void *fdt);
|
||||||
|
|
||||||
|
|
|
||||||
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
|
|
@ -72,6 +72,7 @@ tmp.*
|
||||||
/truncated_property
|
/truncated_property
|
||||||
/truncated_string
|
/truncated_string
|
||||||
/truncated_memrsv
|
/truncated_memrsv
|
||||||
|
/unterminated_memrsv
|
||||||
/utilfdt_test
|
/utilfdt_test
|
||||||
/value-labels
|
/value-labels
|
||||||
/get_next_tag_invalid_prop_len
|
/get_next_tag_invalid_prop_len
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ LIB_TESTS_L = get_mem_rsv \
|
||||||
fs_tree1
|
fs_tree1
|
||||||
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
||||||
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv
|
LIBTREE_TESTS_L = truncated_property truncated_string \
|
||||||
|
truncated_memrsv unterminated_memrsv
|
||||||
|
|
||||||
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
|
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ tests += [
|
||||||
'truncated_memrsv',
|
'truncated_memrsv',
|
||||||
'truncated_property',
|
'truncated_property',
|
||||||
'truncated_string',
|
'truncated_string',
|
||||||
|
'unterminated_memrsv',
|
||||||
]
|
]
|
||||||
|
|
||||||
test_deps = [testutil_dep, util_dep, libfdt_dep]
|
test_deps = [testutil_dep, util_dep, libfdt_dep]
|
||||||
|
|
|
||||||
|
|
@ -495,6 +495,7 @@ libfdt_tests () {
|
||||||
run_test truncated_property
|
run_test truncated_property
|
||||||
run_test truncated_string
|
run_test truncated_string
|
||||||
run_test truncated_memrsv
|
run_test truncated_memrsv
|
||||||
|
run_test unterminated_memrsv
|
||||||
|
|
||||||
# Check aliases support in fdt_path_offset
|
# Check aliases support in fdt_path_offset
|
||||||
run_dtc_test -I dts -O dtb -o aliases.dtb "$SRCDIR/aliases.dts"
|
run_dtc_test -I dts -O dtb -o aliases.dtb "$SRCDIR/aliases.dts"
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ extern struct fdt_header bad_prop_char;
|
||||||
extern struct fdt_header ovf_size_strings;
|
extern struct fdt_header ovf_size_strings;
|
||||||
extern struct fdt_header truncated_string;
|
extern struct fdt_header truncated_string;
|
||||||
extern struct fdt_header truncated_memrsv;
|
extern struct fdt_header truncated_memrsv;
|
||||||
|
extern struct fdt_header unterminated_memrsv;
|
||||||
extern struct fdt_header two_roots;
|
extern struct fdt_header two_roots;
|
||||||
extern struct fdt_header named_root;
|
extern struct fdt_header named_root;
|
||||||
#endif /* ! __ASSEMBLER__ */
|
#endif /* ! __ASSEMBLER__ */
|
||||||
|
|
|
||||||
|
|
@ -291,6 +291,23 @@ truncated_memrsv_rsvmap_end:
|
||||||
|
|
||||||
truncated_memrsv_end:
|
truncated_memrsv_end:
|
||||||
|
|
||||||
|
/* unterminated_memrsv */
|
||||||
|
treehdr unterminated_memrsv
|
||||||
|
|
||||||
|
unterminated_memrsv_rsvmap:
|
||||||
|
rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
|
||||||
|
unterminated_memrsv_rsvmap_end:
|
||||||
|
|
||||||
|
unterminated_memrsv_struct:
|
||||||
|
beginn ""
|
||||||
|
endn
|
||||||
|
fdtlong FDT_END
|
||||||
|
unterminated_memrsv_struct_end:
|
||||||
|
|
||||||
|
unterminated_memrsv_strings:
|
||||||
|
unterminated_memrsv_strings_end:
|
||||||
|
|
||||||
|
unterminated_memrsv_end:
|
||||||
|
|
||||||
/* two root nodes */
|
/* two root nodes */
|
||||||
treehdr two_roots
|
treehdr two_roots
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,12 @@
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "testdata.h"
|
#include "testdata.h"
|
||||||
|
|
||||||
|
#define SPACE 65536
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
void *fdt = &truncated_memrsv;
|
void *fdt = &truncated_memrsv;
|
||||||
|
void *buf;
|
||||||
int err;
|
int err;
|
||||||
uint64_t addr, size;
|
uint64_t addr, size;
|
||||||
|
|
||||||
|
|
@ -46,5 +49,11 @@ int main(int argc, char *argv[])
|
||||||
FAIL("fdt_get_mem_rsv(1) returned %d instead of -FDT_ERR_BADOFFSET",
|
FAIL("fdt_get_mem_rsv(1) returned %d instead of -FDT_ERR_BADOFFSET",
|
||||||
err);
|
err);
|
||||||
|
|
||||||
|
buf = xmalloc(SPACE);
|
||||||
|
err = fdt_open_into(fdt, buf, SPACE);
|
||||||
|
if (err != -FDT_ERR_TRUNCATED)
|
||||||
|
FAIL("fdt_open_into() returned %d instead of -FDT_ERR_TRUNCATED",
|
||||||
|
err);
|
||||||
|
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
67
tests/unterminated_memrsv.c
Normal file
67
tests/unterminated_memrsv.c
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
/*
|
||||||
|
* libfdt - Flat Device Tree manipulation
|
||||||
|
* Testcase for misbehaviour on an unterminated memrsv map
|
||||||
|
* Copyright Red Hat
|
||||||
|
*
|
||||||
|
* Based on a proof of concept report from:
|
||||||
|
* Moshe Strauss <moshestrauss10@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <libfdt.h>
|
||||||
|
|
||||||
|
#include "tests.h"
|
||||||
|
#include "testdata.h"
|
||||||
|
|
||||||
|
#define SPACE 65536
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
void *fdt = &unterminated_memrsv;
|
||||||
|
void *buf;
|
||||||
|
int err;
|
||||||
|
uint64_t addr, size;
|
||||||
|
|
||||||
|
test_init(argc, argv);
|
||||||
|
|
||||||
|
err = fdt_check_header(fdt);
|
||||||
|
if (err != 0)
|
||||||
|
FAIL("Bad header: %s", fdt_strerror(err));
|
||||||
|
|
||||||
|
err = fdt_num_mem_rsv(fdt);
|
||||||
|
if (err != -FDT_ERR_TRUNCATED)
|
||||||
|
FAIL("fdt_num_mem_rsv() returned %d instead of -FDT_ERR_TRUNCATED",
|
||||||
|
err);
|
||||||
|
|
||||||
|
err = fdt_get_mem_rsv(fdt, 0, &addr, &size);
|
||||||
|
if (err != 0)
|
||||||
|
FAIL("fdt_get_mem_rsv() failed on first entry: %s",
|
||||||
|
fdt_strerror(err));
|
||||||
|
if ((addr != TEST_ADDR_1) || (size != TEST_SIZE_1))
|
||||||
|
FAIL("Entry doesn't match: (0x%llx, 0x%llx) != (0x%llx, 0x%llx)",
|
||||||
|
(unsigned long long)addr, (unsigned long long)size,
|
||||||
|
TEST_ADDR_1, TEST_SIZE_1);
|
||||||
|
|
||||||
|
err = fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2);
|
||||||
|
if (err != -FDT_ERR_TRUNCATED)
|
||||||
|
FAIL("fdt_add_mem_rsv() returned %d instead of -FDT_ERR_TRUNCATED",
|
||||||
|
err);
|
||||||
|
|
||||||
|
err = fdt_del_mem_rsv(fdt, 0);
|
||||||
|
if (err != -FDT_ERR_TRUNCATED)
|
||||||
|
FAIL("fdt_del_mem_rsv() returned %d instead of -FDT_ERR_TRUNCATED",
|
||||||
|
err);
|
||||||
|
|
||||||
|
buf = xmalloc(SPACE);
|
||||||
|
err = fdt_open_into(fdt, buf, SPACE);
|
||||||
|
if (err != -FDT_ERR_TRUNCATED)
|
||||||
|
FAIL("fdt_open_into() returned %d instead of -FDT_ERR_TRUNCATED",
|
||||||
|
err);
|
||||||
|
|
||||||
|
PASS();
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue