Allow enabling FDT_ASSUME_FRIENDLY to disable extra checks for invalid device tree files. Signed-off-by: Simon Glass <sjg@xxxxxxxxxxxx> --- Changes in v3: None Changes in v2: None libfdt/fdt.c | 29 +++++++++++---------- libfdt/fdt_ro.c | 69 ++++++++++++++++++++++++++++++++----------------- libfdt/fdt_rw.c | 2 +- libfdt/fdt_sw.c | 14 ++++++---- 4 files changed, 71 insertions(+), 43 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 461b938..7fcdaa8 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -106,23 +106,26 @@ int fdt_check_header(const void *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 (fdt_chk_extra()) { + /* Bounds check structure block */ + if (fdt_chk_version() && 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; } diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index a42d329..723f857 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 || (fdt_chk_extra() && 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 (!fdt_chk_extra()) { + 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 (fdt_chk_extra()) { + 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 (fdt_chk_extra() && !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 (fdt_chk_extra() && + (((err = fdt_ro_probe_(fdt)) < 0) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))) + goto fail; nameptr = nh->name; @@ -388,7 +401,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 (fdt_chk_extra() && !prop) { offset = -FDT_ERR_INTERNAL; break; } @@ -461,14 +475,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 (fdt_chk_extra()) { + 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 +617,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 (fdt_chk_extra()) { + 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 +634,7 @@ 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 (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL; return nodedepth; } diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 30b5cfd..08e2981 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -44,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 (fdt_chk_extra() && (err_ = fdt_rw_probe_(fdt)) != 0) \ return err_; \ } diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index c4c7de7..a8c9246 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -41,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt) if (err) return err; - if (fdt_off_dt_strings(fdt) != 0) + if (fdt_chk_extra() && fdt_off_dt_strings(fdt) != 0) return -FDT_ERR_BADSTATE; return 0; } @@ -49,7 +49,7 @@ 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 (fdt_chk_extra() && (err = fdt_sw_probe_memrsv_(fdt)) != 0) \ return err; \ } @@ -63,7 +63,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 (!fdt_chk_extra()) + return 0; + err = fdt_sw_probe_(fdt); if (err) return err; @@ -75,7 +79,7 @@ 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 (fdt_chk_extra() && (err = fdt_sw_probe_struct_(fdt)) != 0) \ return err; \ } @@ -154,7 +158,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 (fdt_chk_extra() && (headsize + tailsize) > fdt_totalsize(fdt)) return -FDT_ERR_INTERNAL; if ((headsize + tailsize) > bufsize) -- 2.24.0.rc0.303.g954a862665-goog