mirror of https://github.com/wolfSSL/wolfBoot.git
F-5747: guard fdt_data_size_ and fdt_splice_string_ against off_dt_strings+size_dt_strings uint32_t overflow
fdt_data_size_() added the two FDT header uint32_t fields without overflow protection; a crafted FDT with off_dt_strings+size_dt_strings>=2^32 caused the sum to wrap to zero. On 32-bit MMU targets (Cortex-M, RV32, PPC32) the pointer arithmetic in fdt_splice_string_ and fdt_find_add_string_ also wraps, placing 'p' and 'new' at the start of the FDT buffer. All bounds checks in fdt_splice_ then pass (p==end==fdt, oldlen==0, newlen<totalsize), and the subsequent memcpy writes the property-name string directly over the FDT header, corrupting magic, totalsize, and struct offsets. Fix by computing the sum in 64-bit in fdt_data_size_ and returning -FDT_ERR_BADOFFSET on overflow; add a symmetric early-return overflow check in fdt_splice_string_ before the pointer is formed; and propagate the error through fdt_shrink so it does not silently store a zero totalsize.pull/792/head
parent
34231739a5
commit
f7e773333e
20
src/fdt.c
20
src/fdt.c
|
|
@ -96,7 +96,11 @@ static inline int fdt_data_size_(void *fdt)
|
|||
{
|
||||
/* the last portion of a FDT is the DT string, so use its offset and size to
|
||||
* determine total size */
|
||||
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
||||
uint64_t off = (uint64_t)fdt_off_dt_strings(fdt);
|
||||
uint64_t sz = (uint64_t)fdt_size_dt_strings(fdt);
|
||||
if (off + sz > (uint64_t)UINT32_MAX)
|
||||
return -FDT_ERR_BADOFFSET;
|
||||
return (int)(off + sz);
|
||||
}
|
||||
|
||||
static const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|
||||
|
|
@ -329,7 +333,13 @@ static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
|
|||
static int fdt_splice_string_(void *fdt, int newlen)
|
||||
{
|
||||
int err;
|
||||
void *p = (char*)fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
||||
uint32_t off = fdt_off_dt_strings(fdt);
|
||||
uint32_t sz = fdt_size_dt_strings(fdt);
|
||||
void *p;
|
||||
|
||||
if (sz > UINT32_MAX - off)
|
||||
return -FDT_ERR_BADOFFSET;
|
||||
p = (char*)fdt + off + sz;
|
||||
|
||||
if ((err = fdt_splice_(fdt, p, 0, newlen))) {
|
||||
return err;
|
||||
|
|
@ -794,8 +804,10 @@ int fdt_del_node(void *fdt, int nodeoffset)
|
|||
/* adjust the actual total size in the FDT header */
|
||||
int fdt_shrink(void* fdt)
|
||||
{
|
||||
uint32_t total_size = fdt_data_size_(fdt);
|
||||
return fdt_set_totalsize(fdt, total_size);
|
||||
int total_size = fdt_data_size_(fdt);
|
||||
if (total_size < 0)
|
||||
return total_size;
|
||||
return fdt_set_totalsize(fdt, (uint32_t)total_size);
|
||||
}
|
||||
|
||||
/* FTD Fixup API's */
|
||||
|
|
|
|||
|
|
@ -136,6 +136,27 @@ START_TEST(test_fit_load_image_rejects_oversized_prop_len)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
/* off_dt_strings=4, size_dt_strings=0xFFFFFFFC: sum overflows uint32_t to 0.
|
||||
* Before the fix, fdt_data_size_() returned 0 and fdt_shrink() silently set
|
||||
* totalsize=0. After the fix fdt_shrink() must return an error and leave
|
||||
* totalsize unchanged. */
|
||||
START_TEST(test_fdt_shrink_rejects_dt_strings_area_overflow)
|
||||
{
|
||||
static uint8_t buf[256];
|
||||
int rc;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
fdt_set_totalsize(buf, sizeof(buf));
|
||||
fdt_set_off_dt_strings(buf, 4);
|
||||
fdt_set_size_dt_strings(buf, 0xFFFFFFFC);
|
||||
|
||||
rc = fdt_shrink(buf);
|
||||
|
||||
ck_assert_int_lt(rc, 0);
|
||||
ck_assert_uint_eq(fdt_totalsize(buf), sizeof(buf));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite *fdt_suite(void)
|
||||
{
|
||||
Suite *s = suite_create("fdt");
|
||||
|
|
@ -144,6 +165,7 @@ static Suite *fdt_suite(void)
|
|||
tcase_add_test(tc, test_fdt_get_string_rejects_out_of_range_offset);
|
||||
tcase_add_test(tc, test_fdt_get_string_returns_string_with_valid_offset);
|
||||
tcase_add_test(tc, test_fit_load_image_rejects_oversized_prop_len);
|
||||
tcase_add_test(tc, test_fdt_shrink_rejects_dt_strings_area_overflow);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
|
|
|
|||
Loading…
Reference in New Issue