Allow enabling FDT_ASSUME_SANE to disable sanity checks. Signed-off-by: Simon Glass <sjg@xxxxxxxxxxxx> --- Changes in v4: None Changes in v3: None Changes in v2: None libfdt/fdt.c | 62 +++++++++++++++++++--------------- libfdt/fdt_ro.c | 73 ++++++++++++++++++++++++++-------------- libfdt/fdt_rw.c | 6 +++- libfdt/fdt_sw.c | 29 ++++++++++------ libfdt/libfdt_internal.h | 9 +++-- 5 files changed, 113 insertions(+), 66 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 3e37a4b..d89c0e0 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -81,38 +81,44 @@ int fdt_check_header(const void *fdt) if (fdt_magic(fdt) != FDT_MAGIC) return -FDT_ERR_BADMAGIC; - hdrsize = fdt_header_size(fdt); 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; + hdrsize = fdt_header_size(fdt); + if (!can_assume(SANE)) { - 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; + if ((fdt_totalsize(fdt) < hdrsize) + || (fdt_totalsize(fdt) > INT_MAX)) + return -FDT_ERR_TRUNCATED; - /* Bounds check structure block */ - if (fdt_version(fdt) < 17) { + /* Bounds check memrsv block */ if (!check_off_(hdrsize, fdt_totalsize(fdt), - fdt_off_dt_struct(fdt))) + fdt_off_mem_rsvmap(fdt))) return -FDT_ERR_TRUNCATED; - } else { + } + + if (!can_assume(SANE)) { + /* 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_struct(fdt), - fdt_size_dt_struct(fdt))) + fdt_off_dt_strings(fdt), + fdt_size_dt_strings(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; } @@ -120,10 +126,11 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { unsigned absoffset = offset + fdt_off_dt_struct(fdt); - if ((absoffset < offset) - || ((absoffset + len) < absoffset) - || (absoffset + len) > fdt_totalsize(fdt)) - return NULL; + if (!can_assume(SANE)) + if ((absoffset < offset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) @@ -142,7 +149,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) *nextoffset = -FDT_ERR_TRUNCATED; tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); - if (!tagp) + if (!can_assume(SANE) && !tagp) return FDT_END; /* premature end */ tag = fdt32_to_cpu(*tagp); offset += FDT_TAGSIZE; @@ -154,13 +161,13 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) do { p = fdt_offset_ptr(fdt, offset++, 1); } while (p && (*p != '\0')); - if (!p) + if (!can_assume(SANE) && !p) return FDT_END; /* premature end */ break; case FDT_PROP: lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); - if (!lenp) + if (!can_assume(SANE) && !lenp) return FDT_END; /* premature end */ /* skip-name offset, length and value */ offset += sizeof(struct fdt_property) - FDT_TAGSIZE @@ -179,7 +186,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) return FDT_END; } - if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) + if (!can_assume(SANE) && + !fdt_offset_ptr(fdt, startoffset, offset - startoffset)) return FDT_END; /* premature end */ *nextoffset = FDT_TAGALIGN(offset); diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index a5c2797..5615bff 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -16,7 +16,7 @@ static int fdt_nodename_eq_(const void *fdt, int offset, int olen; const char *p = fdt_get_name(fdt, offset, &olen); - if (!p || olen < len) + if (!p || (!can_assume(SANE) && olen < len)) /* short match */ return 0; @@ -33,17 +33,26 @@ 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); + int32_t totalsize; + uint32_t absoffset; size_t len; int err; const char *s, *n; + if (can_assume(SANE)) { + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; + + if (lenp) + *lenp = strlen(s); + return s; + } + totalsize = fdt_ro_probe_(fdt); err = totalsize; if (totalsize < 0) goto fail; err = -FDT_ERR_BADOFFSET; + absoffset = stroffset + fdt_off_dt_strings(fdt); if (absoffset >= totalsize) goto fail; len = totalsize - absoffset; @@ -151,10 +160,13 @@ static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) int offset = n * sizeof(struct fdt_reserve_entry); int absoffset = fdt_off_mem_rsvmap(fdt) + offset; - if (absoffset < fdt_off_mem_rsvmap(fdt)) - return NULL; - if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry)) - return NULL; + if (!can_assume(SANE)) { + if (absoffset < fdt_off_mem_rsvmap(fdt)) + return NULL; + if (absoffset > fdt_totalsize(fdt) - + sizeof(struct fdt_reserve_entry)) + return NULL; + } return fdt_mem_rsv_(fdt, n); } @@ -164,7 +176,7 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) FDT_RO_PROBE(fdt); re = fdt_mem_rsv(fdt, n); - if (!re) + if (!can_assume(SANE) && !re) return -FDT_ERR_BADOFFSET; *address = fdt64_ld(&re->address); @@ -289,9 +301,10 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) const char *nameptr; int err; - if (((err = fdt_ro_probe_(fdt)) < 0) - || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) - goto fail; + if (!can_assume(SANE) && + (((err = fdt_ro_probe_(fdt)) < 0) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))) + goto fail; nameptr = nh->name; @@ -346,7 +359,8 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, int err; const struct fdt_property *prop; - if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { + if (!can_assume(SANE) && + (err = fdt_check_prop_offset_(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; @@ -388,7 +402,8 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, (offset = fdt_next_property_offset(fdt, offset))) { const struct fdt_property *prop; - if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) { + prop = fdt_get_property_by_offset_(fdt, offset, lenp); + if (!can_assume(SANE) && !prop) { offset = -FDT_ERR_INTERNAL; break; } @@ -461,14 +476,19 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, if (namep) { const char *name; int namelen; - name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), - &namelen); - if (!name) { - if (lenp) - *lenp = namelen; - return NULL; + + if (!can_assume(SANE)) { + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), + &namelen); + if (!name) { + if (lenp) + *lenp = namelen; + return NULL; + } + *namep = name; + } else { + *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff)); } - *namep = name; } /* Handle realignment */ @@ -598,10 +618,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, } } - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; + if (!can_assume(SANE)) { + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + } return offset; /* error from fdt_next_node() */ } @@ -613,7 +635,8 @@ int fdt_node_depth(const void *fdt, int nodeoffset) err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); if (err) - return (err < 0) ? err : -FDT_ERR_INTERNAL; + return (can_assume(SANE) || err < 0) ? err : + -FDT_ERR_INTERNAL; return nodedepth; } diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 8795947..1dd9cf0 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -13,6 +13,8 @@ static int fdt_blocks_misordered_(const void *fdt, int mem_rsv_size, int struct_size) { + if (can_assume(SANE)) + return false; return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) || (fdt_off_dt_struct(fdt) < (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) @@ -24,6 +26,8 @@ static int fdt_blocks_misordered_(const void *fdt, static int fdt_rw_probe_(void *fdt) { + if (can_assume(SANE)) + return 0; FDT_RO_PROBE(fdt); if (fdt_version(fdt) < 17) @@ -40,7 +44,7 @@ static int fdt_rw_probe_(void *fdt) #define FDT_RW_PROBE(fdt) \ { \ int err_; \ - if ((err_ = fdt_rw_probe_(fdt)) != 0) \ + if (!can_assume(SANE) && (err_ = fdt_rw_probe_(fdt)) != 0) \ return err_; \ } diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 76bea22..cd0032a 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -12,17 +12,20 @@ static int fdt_sw_probe_(void *fdt) { - if (fdt_magic(fdt) == FDT_MAGIC) - return -FDT_ERR_BADSTATE; - else if (fdt_magic(fdt) != FDT_SW_MAGIC) - return -FDT_ERR_BADMAGIC; + if (!can_assume(SANE)) { + if (fdt_magic(fdt) == FDT_MAGIC) + return -FDT_ERR_BADSTATE; + else if (fdt_magic(fdt) != FDT_SW_MAGIC) + return -FDT_ERR_BADMAGIC; + } + return 0; } #define FDT_SW_PROBE(fdt) \ { \ int err; \ - if ((err = fdt_sw_probe_(fdt)) != 0) \ + if (!can_assume(SANE) && (err = fdt_sw_probe_(fdt)) != 0) \ return err; \ } @@ -38,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt) if (err) return err; - if (fdt_off_dt_strings(fdt) != 0) + if (!can_assume(SANE) && fdt_off_dt_strings(fdt) != 0) return -FDT_ERR_BADSTATE; return 0; } @@ -46,7 +49,8 @@ static int fdt_sw_probe_memrsv_(void *fdt) #define FDT_SW_PROBE_MEMRSV(fdt) \ { \ int err; \ - if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ + if (!can_assume(SANE) && \ + (err = fdt_sw_probe_memrsv_(fdt)) != 0) \ return err; \ } @@ -60,7 +64,11 @@ static int fdt_sw_probe_memrsv_(void *fdt) */ static int fdt_sw_probe_struct_(void *fdt) { - int err = fdt_sw_probe_(fdt); + int err; + + if (can_assume(SANE)) + return 0; + err = fdt_sw_probe_(fdt); if (err) return err; @@ -72,7 +80,8 @@ static int fdt_sw_probe_struct_(void *fdt) #define FDT_SW_PROBE_STRUCT(fdt) \ { \ int err; \ - if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ + if (!can_assume(SANE) && \ + (err = fdt_sw_probe_struct_(fdt)) != 0) \ return err; \ } @@ -151,7 +160,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize) headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); - if ((headsize + tailsize) > fdt_totalsize(fdt)) + if (!can_assume(SANE) && (headsize + tailsize) > fdt_totalsize(fdt)) return -FDT_ERR_INTERNAL; if ((headsize + tailsize) > bufsize) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 198480c..4612fd0 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -13,9 +13,12 @@ int32_t fdt_ro_probe_(const void *fdt); #define FDT_RO_PROBE(fdt) \ { \ - int32_t totalsize_; \ - if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ - return totalsize_; \ + int32_t totalsize_; \ + if (!can_assume(SANE)) { \ + totalsize_ = fdt_ro_probe_(fdt); \ + if (totalsize_ < 0) \ + return totalsize_; \ + } \ } int fdt_check_node_offset_(const void *fdt, int offset); -- 2.24.0.rc1.363.gb1bccd3e3d-goog