diff options
-rw-r--r-- | cpukit/dtc/libfdt/fdt.c | 57 | ||||
-rw-r--r-- | cpukit/include/libfdt.h | 15 | ||||
-rw-r--r-- | cpukit/include/libfdt_env.h | 1 |
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)) |