Ensure that the alias found is valid i.e. An alias value is a device path and is encoded as a string. The value represents the full path to a node, ... This protects against a stack overflow (fdt_path_offset_namelen() calls fdt_get_alias_namelen() then fdt_path_offset(alias), ...) when /aliases has an empty property with an empty name. Co-developed-by: Mike McTernan <mikemcternan@xxxxxxxxxx> Signed-off-by: Pierre-Clément Tosi <ptosi@xxxxxxxxxx> --- libfdt/fdt_ro.c | 11 ++++++++++- tests/aliases.dts | 3 +++ tests/get_alias.c | 12 +++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index c4c520c..bda5c0d 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) && + !(len > 0 && alias && memchr(alias, '\0', len) && *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..8820974 100644 --- a/tests/aliases.dts +++ b/tests/aliases.dts @@ -8,6 +8,9 @@ s1 = &sub1; ss1 = &subsub1; sss1 = &subsubsub1; + badpath = "wrong"; + badpathlong = "wrong/with/parts"; + empty = ""; }; sub1: subnode@1 { diff --git a/tests/get_alias.c b/tests/get_alias.c index fb2c38c..4f3f6fd 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,6 +43,9 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); + check_alias(fdt, NULL, "badpath"); + check_alias(fdt, NULL, "badpathlong"); + check_alias(fdt, NULL, "empty"); check_alias(fdt, "/subnode@1", "s1"); check_alias(fdt, "/subnode@1/subsubnode", "ss1"); check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1"); -- 2.42.0.609.gbb76f46606-goog -- Pierre