fdt: Check for overlapping data and FDT
authorSimon Glass <sjg@chromium.org>
Wed, 21 Dec 2022 23:08:21 +0000 (16:08 -0700)
committerSimon Glass <sjg@chromium.org>
Wed, 18 Jan 2023 18:49:13 +0000 (11:49 -0700)
If the FDT overlaps with the data region of the image, or with the stack,
it can become corrupted before relocation. Add a check for this, behind a
debug flag, as it can be very confusing and time-consuming to debug.

Signed-off-by: Simon Glass <sjg@chromium.org>
lib/fdtdec.c

index 03c9cea..8d5c688 100644 (file)
@@ -1231,6 +1231,29 @@ static void *fdt_find_separate(void)
 #else
        /* FDT is at end of image */
        fdt_blob = (ulong *)&_end;
+
+       if (_DEBUG && !fdtdec_prepare_fdt(fdt_blob)) {
+               int stack_ptr;
+               const void *top = fdt_blob + fdt_totalsize(fdt_blob);
+
+               /*
+                * Perform a sanity check on the memory layout. If this fails,
+                * it indicates that the device tree is positioned above the
+                * global data pointer or the stack pointer. This should not
+                * happen.
+                *
+                * If this fails, check that SYS_INIT_SP_ADDR has enough space
+                * below it for SYS_MALLOC_F_LEN and global_data, as well as the
+                * stack, without overwriting the device tree or U-Boot itself.
+                * Since the device tree is sitting at _end (the start of the
+                * BSS region), we need the top of the device tree to be below
+                * any memory allocated by board_init_f_alloc_reserve().
+                */
+               if (top > (void *)gd || top > (void *)&stack_ptr) {
+                       printf("FDT %p gd %p\n", fdt_blob, gd);
+                       panic("FDT overlap");
+               }
+       }
 #endif
 
        return fdt_blob;