[PATCH v3] lib: fdtdec: validate bloblist FDT before consuming libfdt size

Raymond Mao raymondmaoca at gmail.com
Wed May 6 16:55:33 CEST 2026


From: Raymond Mao <raymond.mao at riscstar.com>

Coverity Scan defects are observed in fdtdec_apply_bloblist_dtos(),
since the live FDT taken from the bloblist is passed to libfdt helpers
which consume header size/offset fields:
- fdt_open_into()
- fdt_pack()

Validate the bloblist FDT with fdt_check_full() before calling
fdt_open_into() and again after applying overlays before calling
fdt_pack(). This makes the libfdt consumers operate on a checked FDT
blob while keeping the existing flow unchanged.

Also normalize libfdt return codes from this path to errno values,
including the overlay callback path through bloblist_apply_blobs().

Fixes: b70cbbfbf94f ("fdtdec: apply DT overlays from bloblist")
Addresses-Coverity-ID: CID 645837: (TAINTED_SCALAR)
Signed-off-by: Raymond Mao <raymond.mao at riscstar.com>
---
changes in v2:
- Rebased on master.
changes in v3:
- replace the local helper fdtdec_get_valid_fdt_size() with
  fdt_check_full().
- remove the check after fdt_pack().
- add helper to map FDT_ERR to errno, and normalize return codes of
  fdtdec_apply_dto_blob() and fdtdec_apply_bloblist_dtos().

 lib/fdtdec.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 2d66860f6ed..c67b6e8c133 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1729,19 +1729,38 @@ static int fdtdec_match_dto_compatible(const void *base, const void *dto)
 	return 0;
 }
 
+static inline int fdtdec_ret_to_errno(int ret)
+{
+	switch (ret) {
+	case -FDT_ERR_NOTFOUND:
+		return -ENOENT;
+	case -FDT_ERR_EXISTS:
+		return -EEXIST;
+	case -FDT_ERR_NOSPACE:
+	case -FDT_ERR_NOPHANDLES:
+		return -ENOSPC;
+	default:
+		return -EINVAL;
+	}
+}
+
 static int fdtdec_apply_dto_blob(void **blob, __maybe_unused int size)
 {
 	int ret;
 
 	ret = fdt_check_header(*blob);
 	if (ret)
-		return ret;
+		return fdtdec_ret_to_errno(ret);
 
 	ret = fdtdec_match_dto_compatible(gd->fdt_blob, *blob);
 	if (ret)
 		return ret;
 
-	return fdt_overlay_apply_verbose((void *)gd->fdt_blob, *blob);
+	ret = fdt_overlay_apply_verbose((void *)gd->fdt_blob, *blob);
+	if (ret)
+		return fdtdec_ret_to_errno(ret);
+
+	return 0;
 }
 
 static int fdtdec_apply_bloblist_dtos(void)
@@ -1760,6 +1779,10 @@ static int fdtdec_apply_bloblist_dtos(void)
 	if (live_fdt != gd->fdt_blob)
 		return -ENOENT;
 
+	ret = fdt_check_full(live_fdt, blob_size);
+	if (ret)
+		return fdtdec_ret_to_errno(ret);
+
 	/* Calculate the allowed padded size */
 	padded_size = fdt_totalsize(live_fdt) + CONFIG_SYS_FDT_PAD;
 	max_size = bloblist_get_total_size() - bloblist_get_size() + blob_size;
@@ -1772,20 +1795,25 @@ static int fdtdec_apply_bloblist_dtos(void)
 		if (ret)
 			return ret;
 
+		blob_size = padded_size;
 		ret = fdt_open_into(live_fdt, live_fdt, padded_size);
 		if (ret)
-			return ret;
+			return fdtdec_ret_to_errno(ret);
 	}
 
 	ret = bloblist_apply_blobs(BLOBLISTT_FDT_OVERLAY, fdtdec_apply_dto_blob);
 	if (ret)
 		return ret;
 
-	/* Shrink the blob to the actual FDT size */
+	ret = fdt_check_full(live_fdt, blob_size);
+	if (ret)
+		return fdtdec_ret_to_errno(ret);
+
 	ret = fdt_pack(live_fdt);
 	if (ret)
-		return ret;
+		return fdtdec_ret_to_errno(ret);
 
+	/* Shrink the blob to the actual FDT size */
 	return bloblist_resize(BLOBLISTT_CONTROL_FDT, fdt_totalsize(live_fdt));
 }
 
-- 
2.25.1



More information about the U-Boot mailing list