From 4902d42398555e138d34e6c7f078def03cdb17d4 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 9 May 2019 19:41:20 +1000 Subject: libfdt: Ensure fdt_add_property frees allocated name string on failure If fdt_add_property or fdt_property_placeholder fail after allocating a string for the name, they return without freeing that string. This does not change the structure of the tree, but in very specific cases it could lead to undesirable space consumption. Fix this by rolling back the string allocation in this situation. Signed-off-by: Nicholas Piggin Message-Id: <20190509094122.834-2-npiggin@gmail.com> Signed-off-by: David Gibson --- cpukit/dtc/libfdt/fdt_sw.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'cpukit/dtc/libfdt/fdt_sw.c') diff --git a/cpukit/dtc/libfdt/fdt_sw.c b/cpukit/dtc/libfdt/fdt_sw.c index 9fa4a94d83..113f28ad3f 100644 --- a/cpukit/dtc/libfdt/fdt_sw.c +++ b/cpukit/dtc/libfdt/fdt_sw.c @@ -262,7 +262,16 @@ int fdt_end_node(void *fdt) return 0; } -static int fdt_find_add_string_(void *fdt, const char *s) +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, strtabsize - len); +} + +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) { char *strtab = (char *)fdt + fdt_totalsize(fdt); const char *p; @@ -270,11 +279,15 @@ static int fdt_find_add_string_(void *fdt, const char *s) int len = strlen(s) + 1; int struct_top, offset; + *allocated = 0; + p = fdt_find_string_(strtab - strtabsize, strtabsize, s); if (p) return p - strtab; /* Add it */ + *allocated = 1; + offset = -strtabsize - len; struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); if (fdt_totalsize(fdt) + offset < struct_top) @@ -289,16 +302,20 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) { struct fdt_property *prop; int nameoff; + int allocated; FDT_SW_PROBE_STRUCT(fdt); - nameoff = fdt_find_add_string_(fdt, name); + nameoff = fdt_find_add_string_(fdt, name, &allocated); if (nameoff == 0) return -FDT_ERR_NOSPACE; prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); - if (! prop) + if (! prop) { + if (allocated) + fdt_del_last_string_(fdt, name); return -FDT_ERR_NOSPACE; + } prop->tag = cpu_to_fdt32(FDT_PROP); prop->nameoff = cpu_to_fdt32(nameoff); -- cgit v1.2.3