Changeset 72273b6 in rtems


Ignore:
Timestamp:
Nov 14, 2017, 11:45:56 AM (19 months ago)
Author:
David Gibson <david@…>
Branches:
master
Children:
6bc883b
Parents:
8073f95e
git-author:
David Gibson <david@…> (11/14/17 11:45:56)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/19/18 05:01:12)
Message:

libfdt: Safer access to strings section

fdt_string() is used to retrieve strings from a DT blob's strings section.
It's rarely used directly, but is widely used internally.

However, it doesn't do any bounds checking, which means in the case of a
corrupted blob it could access bad memory, which libfdt is supposed to
avoid.

This write a safe alternative to fdt_string, fdt_get_string(). It checks
both that the given offset is within the string section and that the string
it points to is properly \0 terminated within the section. It also returns
the string's length as a convenience (since it needs to determine to do the
checks anyway).

fdt_string() is rewritten in terms of fdt_get_string() for compatibility.

Most of the diff here is actually testing infrastructure.

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

Location:
cpukit
Files:
2 edited

Legend:

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

    r8073f95e r72273b6  
    7777}
    7878
     79const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
     80{
     81        uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt);
     82        size_t len;
     83        int err;
     84        const char *s, *n;
     85
     86        err = fdt_ro_probe_(fdt);
     87        if (err != 0)
     88                goto fail;
     89
     90        err = -FDT_ERR_BADOFFSET;
     91        if (absoffset >= fdt_totalsize(fdt))
     92                goto fail;
     93        len = fdt_totalsize(fdt) - absoffset;
     94
     95        if (fdt_magic(fdt) == FDT_MAGIC) {
     96                if (stroffset < 0)
     97                        goto fail;
     98                if (fdt_version(fdt) >= 17) {
     99                        if (stroffset >= fdt_size_dt_strings(fdt))
     100                                goto fail;
     101                        if ((fdt_size_dt_strings(fdt) - stroffset) < len)
     102                                len = fdt_size_dt_strings(fdt) - stroffset;
     103                }
     104        } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
     105                if ((stroffset >= 0)
     106                    || (stroffset < -fdt_size_dt_strings(fdt)))
     107                        goto fail;
     108                if ((-stroffset) < len)
     109                        len = -stroffset;
     110        } else {
     111                err = -FDT_ERR_INTERNAL;
     112                goto fail;
     113        }
     114
     115        s = (const char *)fdt + absoffset;
     116        n = memchr(s, '\0', len);
     117        if (!n) {
     118                /* missing terminating NULL */
     119                err = -FDT_ERR_TRUNCATED;
     120                goto fail;
     121        }
     122
     123        if (lenp)
     124                *lenp = n - s;
     125        return s;
     126
     127fail:
     128        if (lenp)
     129                *lenp = err;
     130        return NULL;
     131}
     132
    79133const char *fdt_string(const void *fdt, int stroffset)
    80134{
    81         return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
     135        return fdt_get_string(fdt, stroffset, NULL);
    82136}
    83137
     
    85139                          const char *s, int len)
    86140{
    87         const char *p = fdt_string(fdt, stroffset);
    88 
    89         return (strlen(p) == len) && (memcmp(p, s, len) == 0);
     141        int slen;
     142        const char *p = fdt_get_string(fdt, stroffset, &slen);
     143
     144        return p && (slen == len) && (memcmp(p, s, len) == 0);
    90145}
    91146
  • cpukit/include/libfdt.h

    r8073f95e r72273b6  
    289289
    290290/**
     291 * fdt_get_string - retrieve a string from the strings block of a device tree
     292 * @fdt: pointer to the device tree blob
     293 * @stroffset: offset of the string within the strings block (native endian)
     294 * @lenp: optional pointer to return the string's length
     295 *
     296 * fdt_get_string() retrieves a pointer to a single string from the
     297 * strings block of the device tree blob at fdt, and optionally also
     298 * returns the string's length in *lenp.
     299 *
     300 * returns:
     301 *     a pointer to the string, on success
     302 *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
     303 */
     304const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
     305
     306/**
    291307 * fdt_string - retrieve a string from the strings block of a device tree
    292308 * @fdt: pointer to the device tree blob
     
    298314 * returns:
    299315 *     a pointer to the string, on success
    300  *     NULL, if stroffset is out of bounds
     316 *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
    301317 */
    302318const char *fdt_string(const void *fdt, int stroffset);
Note: See TracChangeset for help on using the changeset viewer.