summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/dtc/libfdt/fdt.c57
-rw-r--r--cpukit/include/libfdt.h15
-rw-r--r--cpukit/include/libfdt_env.h1
3 files changed, 66 insertions, 7 deletions
diff --git a/cpukit/dtc/libfdt/fdt.c b/cpukit/dtc/libfdt/fdt.c
index 8bbf2dc894..5f1e57a5bd 100644
--- a/cpukit/dtc/libfdt/fdt.c
+++ b/cpukit/dtc/libfdt/fdt.c
@@ -79,9 +79,64 @@ int fdt_ro_probe_(const void *fdt)
return 0;
}
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
+{
+ return (off >= hdrsize) && (off <= totalsize);
+}
+
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
+ uint32_t base, uint32_t size)
+{
+ if (!check_off_(hdrsize, totalsize, base))
+ return 0; /* block start out of bounds */
+ if ((base + size) < base)
+ return 0; /* overflow */
+ if (!check_off_(hdrsize, totalsize, base + size))
+ return 0; /* block end out of bounds */
+ return 1;
+}
+
int fdt_check_header(const void *fdt)
{
- return fdt_ro_probe_(fdt);
+ size_t hdrsize = FDT_V16_SIZE;
+
+ if (fdt_magic(fdt) != FDT_MAGIC)
+ return -FDT_ERR_BADMAGIC;
+ if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+ || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION))
+ return -FDT_ERR_BADVERSION;
+ if (fdt_version(fdt) < fdt_last_comp_version(fdt))
+ return -FDT_ERR_BADVERSION;
+
+ if (fdt_version(fdt) >= 17)
+ hdrsize = FDT_V17_SIZE;
+
+ if ((fdt_totalsize(fdt) < hdrsize)
+ || (fdt_totalsize(fdt) > INT_MAX))
+ return -FDT_ERR_TRUNCATED;
+
+ /* Bounds check memrsv block */
+ if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt)))
+ return -FDT_ERR_TRUNCATED;
+
+ /* Bounds check structure block */
+ if (fdt_version(fdt) < 17) {
+ if (!check_off_(hdrsize, fdt_totalsize(fdt),
+ fdt_off_dt_struct(fdt)))
+ return -FDT_ERR_TRUNCATED;
+ } else {
+ if (!check_block_(hdrsize, fdt_totalsize(fdt),
+ fdt_off_dt_struct(fdt),
+ fdt_size_dt_struct(fdt)))
+ return -FDT_ERR_TRUNCATED;
+ }
+
+ /* Bounds check strings block */
+ if (!check_block_(hdrsize, fdt_totalsize(fdt),
+ fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt)))
+ return -FDT_ERR_TRUNCATED;
+
+ return 0;
}
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
diff --git a/cpukit/include/libfdt.h b/cpukit/include/libfdt.h
index c8c00fa865..837c5e27ee 100644
--- a/cpukit/include/libfdt.h
+++ b/cpukit/include/libfdt.h
@@ -90,8 +90,9 @@
/* Error codes: codes for bad device tree blobs */
#define FDT_ERR_TRUNCATED 8
- /* FDT_ERR_TRUNCATED: Structure block of the given device tree
- * ends without an FDT_END tag. */
+ /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
+ * terminated (overflows, goes outside allowed bounds, or
+ * isn't properly terminated). */
#define FDT_ERR_BADMAGIC 9
/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
* device tree at all - it is missing the flattened device
@@ -244,18 +245,20 @@ fdt_set_hdr_(size_dt_struct);
#undef fdt_set_hdr_
/**
- * fdt_check_header - sanity check a device tree or possible device tree
+ * fdt_check_header - sanity check a device tree header
* @fdt: pointer to data which might be a flattened device tree
*
* fdt_check_header() checks that the given buffer contains what
- * appears to be a flattened device tree with sane information in its
- * header.
+ * appears to be a flattened device tree, and that the header contains
+ * valid information (to the extent that can be determined from the
+ * header alone).
*
* returns:
* 0, if the buffer appears to contain a valid device tree
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE, standard meanings, as above
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_TRUNCATED, standard meanings, as above
*/
int fdt_check_header(const void *fdt);
diff --git a/cpukit/include/libfdt_env.h b/cpukit/include/libfdt_env.h
index bd24746287..eb2053845c 100644
--- a/cpukit/include/libfdt_env.h
+++ b/cpukit/include/libfdt_env.h
@@ -56,6 +56,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#ifdef __CHECKER__
#define FDT_FORCE __attribute__((force))