diff options
| author | Raymond Mao <[email protected]> | 2026-05-06 10:55:33 -0400 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-05-08 15:49:27 -0600 |
| commit | 0a31d3128ee6928d7eac5b830ef79d0a27e3f0a7 (patch) | |
| tree | 4a9bde626515521f5ec66fce3a98c3ec7d71fdaa | |
| parent | 26b17dbdb0f19efa67365b30d939d3572871e8ca (diff) | |
lib: fdtdec: validate bloblist FDT before consuming libfdt size
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 <[email protected]>
Reviewed-by: Alexander Sverdlin <[email protected]>
| -rw-r--r-- | lib/fdtdec.c | 38 |
1 files 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)); } |
