From: Binarly Vulnerability Research <[email protected]> fdt_get_name() can return NULL and set len to a negative error code. fdt_find_regions() does not check for this, leading to a potential NULL pointer dereference and a buffer out-of-bounds write. fdt_next_region(), fdt_check_full(), and display_fdt_by_regions() also lack validation.
Add NULL checks and propagate the error code from fdt_get_name() to the caller. Signed-off-by: Binarly Vulnerability Research <[email protected]> --- Changes in v2: - Rewrite commit message to be concise per maintainer feedback - Don't mask fdt_get_name() returned error boot/fdt_region.c | 5 +++++ scripts/dtc/libfdt/fdt_ro.c | 3 +++ tools/fdtgrep.c | 3 +++ 3 files changed, 11 insertions(+) diff --git a/boot/fdt_region.c b/boot/fdt_region.c index 295ea08ac91..f0f2568955c 100644 --- a/boot/fdt_region.c +++ b/boot/fdt_region.c @@ -86,6 +86,8 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, if (depth == FDT_MAX_DEPTH) return -FDT_ERR_BADSTRUCTURE; name = fdt_get_name(fdt, offset, &len); + if (!name) + return len; /* The root node must have an empty name */ if (!depth && *name) @@ -553,6 +555,9 @@ int fdt_next_region(const void *fdt, if (p.depth == FDT_MAX_DEPTH) return -FDT_ERR_BADSTRUCTURE; name = fdt_get_name(fdt, offset, &len); + if (!name) + return len; + if (p.end - path + 2 + len >= path_len) return -FDT_ERR_NOSPACE; diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index 3e7e26b4398..d7b424c658f 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -940,6 +940,9 @@ int fdt_check_full(const void *fdt, size_t bufsize) int len; name = fdt_get_name(fdt, offset, &len); + if (!name) + return len; + if (*name || len) return -FDT_ERR_BADLAYOUT; } diff --git a/tools/fdtgrep.c b/tools/fdtgrep.c index b4c041070f5..dba7240001f 100644 --- a/tools/fdtgrep.c +++ b/tools/fdtgrep.c @@ -355,6 +355,9 @@ static int display_fdt_by_regions(struct display_info *disp, const void *blob, case FDT_BEGIN_NODE: name = fdt_get_name(blob, offset, &len); + if (!name) + return len; + fprintf(f, "%*s%s {", depth++ * shift, "", *name ? name : "/"); break; -- 2.53.0

