From: Jan Beulich Date: Tue, 17 Mar 2020 15:20:08 +0000 (+0100) Subject: libfdt: fix undefined behaviour in _fdt_splice() X-Git-Tag: archive/raspbian/4.14.0+80-gd101b417b7-1+rpi1^2~63^2~525 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=1faa954df18733792c33b3f5b1b4de4662cfa892;p=xen.git libfdt: fix undefined behaviour in _fdt_splice() Along the lines of commit d0b3ab0a0f46 ("libfdt: Fix undefined behaviour in fdt_offset_ptr()"), _fdt_splice() similarly may not use pointer arithmetic to do overflow checks. [upstream commit 73d6e9ecb4179b510408bc526240f829262df361] Signed-off-by: Jan Beulich Acked-by: Julien Grall --- diff --git a/xen/common/libfdt/fdt_rw.c b/xen/common/libfdt/fdt_rw.c index ee18bfc298..8b8cd25cc2 100644 --- a/xen/common/libfdt/fdt_rw.c +++ b/xen/common/libfdt/fdt_rw.c @@ -87,7 +87,7 @@ static int _fdt_rw_check_header(void *fdt) return err; \ } -static inline int _fdt_data_size(void *fdt) +static inline unsigned int _fdt_data_size(void *fdt) { return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } @@ -95,13 +95,14 @@ static inline int _fdt_data_size(void *fdt) static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) { char *p = splicepoint; - char *end = (char *)fdt + _fdt_data_size(fdt); + unsigned int dsize = _fdt_data_size(fdt); + size_t soff = p - (char *)fdt; - if (((p + oldlen) < p) || ((p + oldlen) > end)) + if (oldlen < 0 || soff + oldlen < soff || soff + oldlen > dsize) return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) + if (dsize - oldlen + newlen > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; - memmove(p + newlen, p + oldlen, end - p - oldlen); + memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen)); return 0; }