Re: [PATCH v2 1/6] Add a way to control the level of checks in the code

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



On Thu, Aug 01, 2019 at 01:13:58PM -0600, Simon Glass wrote:
> Add a new CHECK_MASK option, which allows for some control over the
> checks used in libfdt. With no checks enabled, libfdt assumes that the
> input data and parameters are all correct and that internal errors cannot
> happen.
> 
> By default all checks are enabled.
> 
> Signed-off-by: Simon Glass <sjg@xxxxxxxxxxxx>

Sorry I've taken so long to look at this.  I think I'm pretty much
convinced by this in outline, just some details to polish.

> ---
> 
> Changes in v2:
> - Add an fdt_ prefix to avoid namespace conflicts
> - Use symbolic names for _check functions and drop leading underscores
> 
>  Makefile        |  6 +++++-
>  libfdt/libfdt.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 54 insertions(+), 2 deletions(-)
> 
> diff --git a/Makefile b/Makefile
> index e955242..9aab665 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -16,7 +16,11 @@ EXTRAVERSION =
>  LOCAL_VERSION =
>  CONFIG_LOCALVERSION =
>  
> -CPPFLAGS = -I libfdt -I .
> +# Control the checks (e.g. to avoid security issues) to include in the code
> +# See libfdt_internal.h for details
> +CHK_MASK ?= 255

Hex for the masks, please.

Also, you mention libfdt_internal.h here, but then change libfdt.h
below.

I think libfdt_internal.h is actually the right choice, see further
comments below.

> +
> +CPPFLAGS = -I libfdt -I . -DFDT_CHK_MASK=$(CHK_MASK)
>  WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
>  	-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
>  CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
> diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
> index 8037f39..5562184 100644
> --- a/libfdt/libfdt.h
> +++ b/libfdt/libfdt.h
> @@ -172,6 +172,53 @@ static inline void fdt64_st(void *property, uint64_t value)
>  	bp[7] = value & 0xff;
>  }
>  
> +/**********************************************************************/
> +/* Checking controls                                                  */
> +/**********************************************************************/
> +
> +#ifndef FDT_CHK_MASK
> +#define FDT_CHK_MASK 255
> +#endif
> +
> +/* Defines the available checks, each of which can be enabled individually */
> +enum {
> +	FDT_MASK_CHK_NONE	= 0,
> +	FDT_MASK_CHK_BASIC	= 1 << 0,
> +	FDT_MASK_CHK_VERSION	= 1 << 1,
> +	FDT_MASK_CHK_EXTRA	= 1 << 2,

I'd prefer to see the comments about what each check covers here,
rather than on the wrapping functions below, so that they're in one
place.

> +};
> +
> +/**
> + * fdt_chk_basic() - see if basic checking of params and DT data is enabled
> + *
> + * This level assumes that the device tree is sane (header metadata and basic
> + * hierarchy are correct). Old device-tree versions are handled
> correctly.

This looks like it needs a bit of an update for the mask based system.

I'd like to see these descriptions expanded a bit too, in particular
each one should make clear what are the prerequisites on the dtb to
work with this option.  So, for basic you need a valid tree, for
version you need a v17 tree.

A general comment in this section should emphasise that turning off
checks will *messily* fail if your tree doesn't meet the requirements.

> + */
> +static inline bool fdt_chk_basic(void)
> +{
> +	return FDT_CHK_MASK & FDT_MASK_CHK_BASIC;
> +}
> +
> +/**
> + * fdt_chk_version() - see if we need to handle old versions of the DT
> + *
> + */
> +static inline bool fdt_chk_version(void)
> +{
> +	return FDT_CHK_MASK & FDT_MASK_CHK_VERSION;
> +}
> +
> +/**
> + * fdt_chk_extra() - see if extra checking is enabled
> + *
> + * This check enables more extensive checking of parameters and the device tree,
> + * making few assumptions about correctness.
> + */
> +static inline bool fdt_chk_extra(void)
> +{
> +	return FDT_CHK_MASK & FDT_MASK_CHK_EXTRA;
> +}
> +
>  /**********************************************************************/
>  /* Traversal functions                                                */
>  /**********************************************************************/
> @@ -269,7 +316,8 @@ fdt_set_hdr_(size_dt_struct);
>  size_t fdt_header_size_(uint32_t version);
>  static inline size_t fdt_header_size(const void *fdt)
>  {
> -	return fdt_header_size_(fdt_version(fdt));
> +	return fdt_chk_version() ? fdt_header_size_(fdt_version(fdt)) :
> +		FDT_V17_SIZE;

So, AFAICT, handling this is the one reason you need the stuff in
libfdt.h rather than libfdt_internal.h.  But even here, the results
could be kinda weird - if a user directly calls fdt_header_size() the
checking-ness will depend on FDT_CHK_MASK in the caller's build rather
than libfdt's build.

I think a better approach is to de-inline fdt_header_size(), at least
for external callers.

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