Browse Source

libfdt: Fix undefined behaviour in fdt_offset_ptr()

Using pointer arithmetic to generate a pointer outside a known object is,
technically, undefined behaviour in C.  Unfortunately, we were using that
in fdt_offset_ptr() to detect overflows.

To fix this we need to do our bounds / overflow checking on the offsets
before constructing pointers from them.

Reported-by: David Binderman <dcb314@hotmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
main
David Gibson 9 years ago
parent
commit
d0b3ab0a0f
  1. 13
      libfdt/fdt.c

13
libfdt/fdt.c

@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)


const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{ {
const char *p; unsigned absoffset = offset + fdt_off_dt_struct(fdt);

if ((absoffset < offset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;


if (fdt_version(fdt) >= 0x11) if (fdt_version(fdt) >= 0x11)
if (((offset + len) < offset) if (((offset + len) < offset)
|| ((offset + len) > fdt_size_dt_struct(fdt))) || ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL; return NULL;


p = _fdt_offset_ptr(fdt, offset); return _fdt_offset_ptr(fdt, offset);

if (p + len < p)
return NULL;
return p;
} }


uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)

Loading…
Cancel
Save