summaryrefslogtreecommitdiffstats
path: root/cpukit/dtc/libfdt
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2019-07-05 13:42:40 +1000
committerSebastian Huber <sebastian.huber@embedded-brains.de>2020-03-02 07:52:20 +0100
commit1a5c324480167b9eca9398a10d95d85a74fcb941 (patch)
tree31f05831da5436c7b74bce3e5f9b7c96cdb9da3f /cpukit/dtc/libfdt
parentlibfdt: Replace GPL/BSD boilerplate/reference with SPDX tags (diff)
downloadrtems-1a5c324480167b9eca9398a10d95d85a74fcb941.tar.bz2
libfdt: Tweak data handling to satisfy Coverity
In libfdt we often sanity test fdt_totalsize(fdt) fairly early, then trust it (but *only* that header field) for the remainder of our work. However, Coverity gets confused by this - it sees the byteswap in fdt32_ld() and assumes that means it is coming from an untrusted source everytime, resulting in many tainted data warnings. Most of these end up with logic in fdt_get_string() as the unsafe destination for this tainted data, so let's tweak the logic there to make it clearer to Coverity that this is ok. We add a sanity test on fdt_totalsize() to fdt_probe_ro_(). Because the interface allows bare ints to be used for offsets, we already have the assumption that totalsize must be 31-bits or less (2GiB would be a ludicrously large fdt). This makes this more explicit. We also make fdt_probe_ro() return the size for convenience, and change the logic in fdt_get_string() to keep it in a local so that Coverity can see that it has already been bounds-checked. Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'cpukit/dtc/libfdt')
-rw-r--r--cpukit/dtc/libfdt/fdt.c9
-rw-r--r--cpukit/dtc/libfdt/fdt_ro.c11
-rw-r--r--cpukit/dtc/libfdt/libfdt_internal.h10
3 files changed, 18 insertions, 12 deletions
diff --git a/cpukit/dtc/libfdt/fdt.c b/cpukit/dtc/libfdt/fdt.c
index 179168ec63..d6ce7c052d 100644
--- a/cpukit/dtc/libfdt/fdt.c
+++ b/cpukit/dtc/libfdt/fdt.c
@@ -15,8 +15,10 @@
* that the given buffer contains what appears to be a flattened
* device tree with sane information in its header.
*/
-int fdt_ro_probe_(const void *fdt)
+int32_t fdt_ro_probe_(const void *fdt)
{
+ uint32_t totalsize = fdt_totalsize(fdt);
+
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
@@ -31,7 +33,10 @@ int fdt_ro_probe_(const void *fdt)
return -FDT_ERR_BADMAGIC;
}
- return 0;
+ if (totalsize < INT32_MAX)
+ return totalsize;
+ else
+ return -FDT_ERR_TRUNCATED;
}
static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
diff --git a/cpukit/dtc/libfdt/fdt_ro.c b/cpukit/dtc/libfdt/fdt_ro.c
index 6fd9ec170d..a5c2797cde 100644
--- a/cpukit/dtc/libfdt/fdt_ro.c
+++ b/cpukit/dtc/libfdt/fdt_ro.c
@@ -33,19 +33,20 @@ static int fdt_nodename_eq_(const void *fdt, int offset,
const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
{
+ int32_t totalsize = fdt_ro_probe_(fdt);
uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt);
size_t len;
int err;
const char *s, *n;
- err = fdt_ro_probe_(fdt);
- if (err != 0)
+ err = totalsize;
+ if (totalsize < 0)
goto fail;
err = -FDT_ERR_BADOFFSET;
- if (absoffset >= fdt_totalsize(fdt))
+ if (absoffset >= totalsize)
goto fail;
- len = fdt_totalsize(fdt) - absoffset;
+ len = totalsize - absoffset;
if (fdt_magic(fdt) == FDT_MAGIC) {
if (stroffset < 0)
@@ -288,7 +289,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
const char *nameptr;
int err;
- if (((err = fdt_ro_probe_(fdt)) != 0)
+ if (((err = fdt_ro_probe_(fdt)) < 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;
diff --git a/cpukit/dtc/libfdt/libfdt_internal.h b/cpukit/dtc/libfdt/libfdt_internal.h
index 7830e550c3..741eeb3150 100644
--- a/cpukit/dtc/libfdt/libfdt_internal.h
+++ b/cpukit/dtc/libfdt/libfdt_internal.h
@@ -11,11 +11,11 @@
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
int fdt_ro_probe_(const void *fdt);
-#define FDT_RO_PROBE(fdt) \
- { \
- int err_; \
- if ((err_ = fdt_ro_probe_(fdt)) != 0) \
- return err_; \
+#define FDT_RO_PROBE(fdt) \
+ { \
+ int totalsize_; \
+ if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \
+ return totalsize_; \
}
int fdt_check_node_offset_(const void *fdt, int offset);