Changeset 72273b6 in rtems for cpukit/dtc


Ignore:
Timestamp:
Nov 14, 2017, 11:45:56 AM (2 years 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@…>

File:
1 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
Note: See TracChangeset for help on using the changeset viewer.