Re: [PATCH v4 3/6] libfdt: Add support for disabling sanity checks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



On Tue, Nov 12, 2019 at 06:54:19PM -0700, Simon Glass wrote:
> Allow enabling FDT_ASSUME_SANE to disable sanity checks.

LGTM, with the exception of the possible splitting of assuming sane
dtb contents from assuming sane parameters mentioned earlier.

> 
> 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);

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux