Changeset 8073f95e in rtems


Ignore:
Timestamp:
Oct 23, 2017, 3:45:56 AM (2 years ago)
Author:
David Gibson <david@…>
Branches:
master
Children:
72273b6
Parents:
c4267b1
git-author:
David Gibson <david@…> (10/23/17 03:45:56)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/19/18 05:01:11)
Message:

libfdt: Make fdt_check_header() more thorough

Currently fdt_check_header() performs only some rudimentary checks, which
is not really what the name suggests. This strengthens fdt_check_header()
to check as much about the blob as is possible from the header alone: as
well as checking the magic number and version, it checks that the total
size is sane, and that all the sub-blocks within the blob lie within the
total size.

  • This broadens the meaning of FDT_ERR_TRUNCATED to cover all sorts of improperly terminated blocks as well as just a structure block without FDT_END.
  • This makes fdt_check_header() only succeed on "complete" blobs, not in-progress sequential write blobs. The only reason this didn't fail before was that this function used to be called by many RO functions which are supposed to also work on incomplete SW blobs.

Signed-off-by: David Gibson <david@…>
Tested-by: Alexey Kardashevskiy <aik@…>
Reviewed-by: Alexey Kardashevskiy <aik@…>
Reviewed-by: Simon Glass <sjg@…>

Location:
cpukit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cpukit/dtc/libfdt/fdt.c

    rc4267b1 r8073f95e  
    8080}
    8181
     82static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
     83{
     84        return (off >= hdrsize) && (off <= totalsize);
     85}
     86
     87static int check_block_(uint32_t hdrsize, uint32_t totalsize,
     88                        uint32_t base, uint32_t size)
     89{
     90        if (!check_off_(hdrsize, totalsize, base))
     91                return 0; /* block start out of bounds */
     92        if ((base + size) < base)
     93                return 0; /* overflow */
     94        if (!check_off_(hdrsize, totalsize, base + size))
     95                return 0; /* block end out of bounds */
     96        return 1;
     97}
     98
    8299int fdt_check_header(const void *fdt)
    83100{
    84         return fdt_ro_probe_(fdt);
     101        size_t hdrsize = FDT_V16_SIZE;
     102
     103        if (fdt_magic(fdt) != FDT_MAGIC)
     104                return -FDT_ERR_BADMAGIC;
     105        if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
     106            || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION))
     107                return -FDT_ERR_BADVERSION;
     108        if (fdt_version(fdt) < fdt_last_comp_version(fdt))
     109                return -FDT_ERR_BADVERSION;
     110
     111        if (fdt_version(fdt) >= 17)
     112                hdrsize = FDT_V17_SIZE;
     113
     114        if ((fdt_totalsize(fdt) < hdrsize)
     115            || (fdt_totalsize(fdt) > INT_MAX))
     116                return -FDT_ERR_TRUNCATED;
     117
     118        /* Bounds check memrsv block */
     119        if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt)))
     120                return -FDT_ERR_TRUNCATED;
     121
     122        /* Bounds check structure block */
     123        if (fdt_version(fdt) < 17) {
     124                if (!check_off_(hdrsize, fdt_totalsize(fdt),
     125                                fdt_off_dt_struct(fdt)))
     126                        return -FDT_ERR_TRUNCATED;
     127        } else {
     128                if (!check_block_(hdrsize, fdt_totalsize(fdt),
     129                                  fdt_off_dt_struct(fdt),
     130                                  fdt_size_dt_struct(fdt)))
     131                        return -FDT_ERR_TRUNCATED;
     132        }
     133
     134        /* Bounds check strings block */
     135        if (!check_block_(hdrsize, fdt_totalsize(fdt),
     136                          fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt)))
     137                return -FDT_ERR_TRUNCATED;
     138
     139        return 0;
    85140}
    86141
  • cpukit/include/libfdt.h

    rc4267b1 r8073f95e  
    9191/* Error codes: codes for bad device tree blobs */
    9292#define FDT_ERR_TRUNCATED       8
    93         /* FDT_ERR_TRUNCATED: Structure block of the given device tree
    94          * ends without an FDT_END tag. */
     93        /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
     94         * terminated (overflows, goes outside allowed bounds, or
     95         * isn't properly terminated).  */
    9596#define FDT_ERR_BADMAGIC        9
    9697        /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
     
    245246
    246247/**
    247  * fdt_check_header - sanity check a device tree or possible device tree
     248 * fdt_check_header - sanity check a device tree header
    248249 * @fdt: pointer to data which might be a flattened device tree
    249250 *
    250251 * fdt_check_header() checks that the given buffer contains what
    251  * appears to be a flattened device tree with sane information in its
    252  * header.
     252 * appears to be a flattened device tree, and that the header contains
     253 * valid information (to the extent that can be determined from the
     254 * header alone).
    253255 *
    254256 * returns:
     
    256258 *     -FDT_ERR_BADMAGIC,
    257259 *     -FDT_ERR_BADVERSION,
    258  *     -FDT_ERR_BADSTATE, standard meanings, as above
     260 *     -FDT_ERR_BADSTATE,
     261 *     -FDT_ERR_TRUNCATED, standard meanings, as above
    259262 */
    260263int fdt_check_header(const void *fdt);
  • cpukit/include/libfdt_env.h

    rc4267b1 r8073f95e  
    5757#include <stdlib.h>
    5858#include <string.h>
     59#include <limits.h>
    5960
    6061#ifdef __CHECKER__
Note: See TracChangeset for help on using the changeset viewer.