Message ID | e2734a4d-fb92-55e7-c08b-423f38049776@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | libfdt: eliminate UB pointer validation | expand |
Hi Jan, On 13/03/2020 07:35, Jan Beulich wrote: > From: David Gibson <david@gibson.dropbear.id.au> > > 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> > [upstream commit d0b3ab0a0f46ac929b4713da46f7fdcd893dd3bd] > Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Julien Grall <jgrall@amazon.com> Cheers, > > --- a/xen/common/libfdt/fdt.c > +++ b/xen/common/libfdt/fdt.c > @@ -74,18 +74,19 @@ int fdt_check_header(const void *fdt) > > 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 (((offset + len) < offset) > || ((offset + len) > fdt_size_dt_struct(fdt))) > return NULL; > > - p = _fdt_offset_ptr(fdt, offset); > - > - if (p + len < p) > - return NULL; > - return p; > + return _fdt_offset_ptr(fdt, offset); > } > > uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) >
--- a/xen/common/libfdt/fdt.c +++ b/xen/common/libfdt/fdt.c @@ -74,18 +74,19 @@ int fdt_check_header(const void *fdt) 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 (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; - p = _fdt_offset_ptr(fdt, offset); - - if (p + len < p) - return NULL; - return p; + return _fdt_offset_ptr(fdt, offset); } uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)