[PATCH] fdt_region: Check the return value of fdt_get_property_by_offset() calls

Anton Ivanov anton at binarly.io
Fri May 22 14:30:22 CEST 2026


From: Binarly Vulnerability Research <vr at binarly.io>

The fdt_find_regions() function in boot/fdt_region.c walks the FDT
structure block one tag at a time, building the list of regions to
feed into the signature hash. When it sees an FDT_PROP tag it reads
the property header to retrieve the property name:

	case FDT_PROP:
		include = want >= 2;
		stop_at = offset;
		prop = fdt_get_property_by_offset(fdt, offset, NULL);
		str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));

fdt_get_property_by_offset() in scripts/dtc/libfdt/fdt_ro.c
explicitly returns NULL for any FDT with 'fdt_version < 0x10':

const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
						      int offset,
						      int *lenp)
	{
		/* Prior to version 16, properties may need realignment
		* and this API does not work. fdt_getprop_*() will, however. */

		if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
			if (lenp)
				*lenp = -FDT_ERR_BADVERSION;
			return NULL;
		}

		return fdt_get_property_by_offset_(fdt, offset, lenp);
	}

A FIT image with a version less than 0x10 causes 'prop' to be null
on the very first FDT_PROP tag the iterator reaches. The next line
dereferences prop->nameoff, which leads to a null pointer
dereference on platforms where the zero page is not mapped.

The same lack of validation exists in fdt_add_alias_regions() and
in fdt_next_region() in boot/fdt_region.c.

Fix: Validate the returned pointer before use.

Signed-off-by: Binarly Vulnerability Research <vr at binarly.io>
---
 boot/fdt_region.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/boot/fdt_region.c b/boot/fdt_region.c
index 295ea08ac91..0a9d47bb2bd 100644
--- a/boot/fdt_region.c
+++ b/boot/fdt_region.c
@@ -69,6 +69,8 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
 			include = want >= 2;
 			stop_at = offset;
 			prop = fdt_get_property_by_offset(fdt, offset, NULL);
+			if (!prop)
+				return -FDT_ERR_BADSTRUCTURE;
 			str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
 			if (!str)
 				return -FDT_ERR_BADSTRUCTURE;
@@ -271,7 +273,11 @@ int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
 		int target, next;
 
 		prop = fdt_get_property_by_offset(fdt, offset, NULL);
+		if (!prop)
+			return -FDT_ERR_BADSTRUCTURE;
 		name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+		if (!name)
+			return -FDT_ERR_BADSTRUCTURE;
 		target = fdt_path_offset(fdt, name);
 		if (!region_list_contains_offset(info, fdt, target))
 			continue;
@@ -520,7 +526,11 @@ int fdt_next_region(const void *fdt,
 		case FDT_PROP:
 			stop_at = offset;
 			prop = fdt_get_property_by_offset(fdt, offset, NULL);
+			if (!prop)
+				return -FDT_ERR_BADSTRUCTURE;
 			str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+			if (!str)
+				return -FDT_ERR_BADSTRUCTURE;
 			val = h_include(priv, fdt, last_node, FDT_IS_PROP, str,
 					    strlen(str) + 1);
 			if (val == -1) {
-- 
2.53.0



More information about the U-Boot mailing list