On Tue, Oct 10, 2023 at 10:27:25AM +0100, Pierre-Clément Tosi wrote: > Ensure that the alias found matches the device tree specification v0.4: > > Each property of the /aliases node defines an alias. The property > name specifies the alias name. The property value specifies the full > path to a node in the devicetree. > > This protects against a stack overflow caused by > > fdt_path_offset_namelen(fdt, path, namelen) > > calling > > fdt_path_offset(fdt, fdt_get_alias_namelen(fdt, path, namelen)) > > leading to infinite recursion on DTs with "circular" aliases. > > This fix was originally written by Mike McTernan for Android in [1]. > > [1]: https://android.googlesource.com/platform/external/dtc/+/9308e7f9772bd226fea9925b1fc4d53c127ed4d5 > > Signed-off-by: Pierre-Clément Tosi <ptosi@xxxxxxxxxx> Thanks, applied, with Mike McTernan's ack folded in. > > --- > v2 > - replace memchr('/') with check on last character > - add test coverage of a self-referencing alias > - drop redundant test case on alias to non-absolute path > - reference the DT spec and AOSP patch in the commit message > - rephrase the infinite recursion case in the commit message > v3 > - swap (len > 0) and (alias) checks to better align with the API > - point the "relative" alias to a path that exists in the test DT > - simplify the infinite recursion case in the commit message > --- > libfdt/fdt_ro.c | 11 ++++++++++- > tests/aliases.dts | 4 ++++ > tests/get_alias.c | 14 +++++++++++++- > 3 files changed, 27 insertions(+), 2 deletions(-) > > diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c > index c4c520c..9fe2f49 100644 > --- a/libfdt/fdt_ro.c > +++ b/libfdt/fdt_ro.c > @@ -537,7 +537,16 @@ static const void *fdt_path_getprop_namelen(const void *fdt, const char *path, > const char *fdt_get_alias_namelen(const void *fdt, > const char *name, int namelen) > { > - return fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, NULL); > + int len; > + const char *alias; > + > + alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len); > + > + if (!can_assume(VALID_DTB) && > + !(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/')) > + return NULL; > + > + return alias; > } > > const char *fdt_get_alias(const void *fdt, const char *name) > diff --git a/tests/aliases.dts b/tests/aliases.dts > index 853479a..03ed675 100644 > --- a/tests/aliases.dts > +++ b/tests/aliases.dts > @@ -5,6 +5,10 @@ > #size-cells = <0>; > > aliases { > + empty = ""; > + loop = "loop"; > + nonull = [626164]; > + relative = "s1/subsubnode"; > s1 = &sub1; > ss1 = &subsub1; > sss1 = &subsubsub1; > diff --git a/tests/get_alias.c b/tests/get_alias.c > index fb2c38c..d2888d6 100644 > --- a/tests/get_alias.c > +++ b/tests/get_alias.c > @@ -21,9 +21,16 @@ static void check_alias(void *fdt, const char *path, const char *alias) > > aliaspath = fdt_get_alias(fdt, alias); > > - if (path && !aliaspath) > + if (!path && !aliaspath) > + return; > + > + if (!aliaspath) > FAIL("fdt_get_alias(%s) failed\n", alias); > > + if (!path) > + FAIL("fdt_get_alias(%s) returned %s instead of NULL", > + alias, aliaspath); > + > if (strcmp(aliaspath, path) != 0) > FAIL("fdt_get_alias(%s) returned %s instead of %s\n", > alias, aliaspath, path); > @@ -36,9 +43,14 @@ int main(int argc, char *argv[]) > test_init(argc, argv); > fdt = load_blob_arg(argc, argv); > > + check_alias(fdt, NULL, "empty"); > + check_alias(fdt, NULL, "nonull"); > + check_alias(fdt, NULL, "relative"); > check_alias(fdt, "/subnode@1", "s1"); > check_alias(fdt, "/subnode@1/subsubnode", "ss1"); > check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1"); > > + check_alias(fdt, NULL, "loop"); // Might trigger a stack overflow > + > PASS(); > } -- 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