From: David Gibson <david@gibson.dropbear.id.au>
To: "Pierre-Clément Tosi" <ptosi@google.com>
Cc: devicetree-compiler@vger.kernel.org,
Mike McTernan <mikemcternan@google.com>,
Simon Glass <sjg@chromium.org>
Subject: Re: [PATCH v2] libfdt: fdt_get_alias_namelen: Validate aliases
Date: Tue, 10 Oct 2023 15:56:19 +1100 [thread overview]
Message-ID: <ZSTZc6exEXIaVf3X@zatzit> (raw)
In-Reply-To: <20231009142004.m4af5c2utpzoll2e@google.com>
[-- Attachment #1: Type: text/plain, Size: 5400 bytes --]
On Mon, Oct 09, 2023 at 03:20:04PM +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 (if 'path' contains no '/')
Uh.. this still seems confusing, or at least misleadingly specific.
Having a self-referential alias doesn't really have anything to do
with whether the path has any '/' or not.
> 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].
Urgh... I don't love the idea of merging something that doesn't have a
Signed-off from the original author. I guess it's probably ok with
something this small.
> [1]: https://android.googlesource.com/platform/external/dtc/+/9308e7f9772bd226fea9925b1fc4d53c127ed4d5
>
> Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
>
> ---
> 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
> ---
> 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..39b7c68 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 && alias[len - 1] == '\0' && *alias == '/'))
I'd be more confortable with the alias test before the len > 0 test.
It's probably fine either way: if !alias, then len should be an error
code < 0. However, the point is len has a different interpretation
depending on whether alias is NULL or not-NULL, making (len > 0) a
slightly ambiguous statement if we haven't already established which
case we're in.
> + 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..b880176 100644
> --- a/tests/aliases.dts
> +++ b/tests/aliases.dts
> @@ -5,6 +5,10 @@
> #size-cells = <0>;
>
> aliases {
> + empty = "";
> + loop = "loop";
> + nonull = [626164];
> + relative = "rel/at/ive";
Since you're only testing fdt_get_alias() here, rather than the full
path_offset(), this is probably ok, but there is a bit of ambuguity
here in what's wrong with this. What you're testing here is that this
is disallowed as an alias-to-an-alias. But if you were resolving this
with path_offset(), you'd expect NOTFOUND even if aliases-to-aliases
were allowed, both since the alias it's relative to doesn't exist, and
the rest of the path won't resolve anyway.
I think it would be clearer and more robust to use a case here where
the *only* thing wrong with the alias is that it involves another
alias. e.g.
relative = "s1/subsubnode"
That would be an alias resolving to the same thing as 'ss1', if it
were not for the alias-to-an-alias prohibition.
> 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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2023-10-10 4:56 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-09 14:20 [PATCH v2] libfdt: fdt_get_alias_namelen: Validate aliases Pierre-Clément Tosi
2023-10-10 4:56 ` David Gibson [this message]
2023-10-10 9:26 ` Pierre-Clément Tosi
2023-10-11 0:33 ` David Gibson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZSTZc6exEXIaVf3X@zatzit \
--to=david@gibson.dropbear.id.au \
--cc=devicetree-compiler@vger.kernel.org \
--cc=mikemcternan@google.com \
--cc=ptosi@google.com \
--cc=sjg@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.