pseudo_fix_path() incorrectly assumed that 'base' never ends with a slash because it's a canonical path. However, base can be "/" - a path which is canonical and yet starts with a slash. This happens when pseudo_cwd is "/" or when we're starting from a dirfd pointing to "/". The wrong result from pseudo_fix_path() caused the database lookup to fail and made pseudo abort.
Signed-off-by: Tomi Belan <[email protected]> --- Hi. Here is my third patch for 'pseudo'. I included a test that demonstrates the fix. Try "make test" with old and new pseudo_util.c to see the difference. Run it with PSEUDO_DEBUG to see what happens and how it leads to an abort. JFYI: The real fix is to check "baselen == 1". The "rootlen == 1" condition is just for symmetry. Unlike pseudo_cwd and fd_path(), which can be "/", I think pseudo_chroot will never be "/" because pseudo_client_chroot sets it to NULL instead. So rootlen should never be 1. It's just to be safe. pseudo_util.c | 12 +++++++++--- test/test-relative-from-root.sh | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100755 test/test-relative-from-root.sh diff --git a/pseudo_util.c b/pseudo_util.c index e8e9803..64636b7 100644 --- a/pseudo_util.c +++ b/pseudo_util.c @@ -792,9 +792,9 @@ static char *pathbufs[PATHBUFS] = { 0 }; static int pathbuf = 0; /* Canonicalize path. "base", if present, is an already-canonicalized - * path of baselen characters, presumed not to end in a /. path is - * the new path to be canonicalized. The tricky part is that path may - * contain symlinks, which must be resolved. + * path of baselen characters, presumed not to end in a / unless it is + * just "/". path is the new path to be canonicalized. The tricky part + * is that path may contain symlinks, which must be resolved. */ char * pseudo_fix_path(const char *base, const char *path, size_t rootlen, size_t baselen, size_t *lenp, int leave_last) { @@ -808,6 +808,12 @@ pseudo_fix_path(const char *base, const char *path, size_t rootlen, size_t basel pseudo_diag("can't fix empty path.\n"); return 0; } + if (baselen == 1) { + baselen = 0; + } + if (rootlen == 1) { + rootlen = 0; + } newpathlen = pseudo_path_max(); pathlen = strlen(path); /* Crazy shell code (e.g. libtool) can pass in a command pipeline as a path which exceeds the max path diff --git a/test/test-relative-from-root.sh b/test/test-relative-from-root.sh new file mode 100755 index 0000000..e2c230e --- /dev/null +++ b/test/test-relative-from-root.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# pseudo had a bug that made it abort() when looking up a relative path from +# base "/", such as by openat(dirfd_of_root, "foo/bar") or when cwd is /. It +# tried to look up base+"/"+path = "//foo/bar", which is wrong. + +set -e + +touch f1 +relative_pwd=${PWD#/} + +cd / +cat "$relative_pwd/f1" + +rm "$relative_pwd/f1" -- 2.25.1
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#169823): https://lists.openembedded.org/g/openembedded-core/message/169823 Mute This Topic: https://lists.openembedded.org/mt/93231058/21656 Group Owner: [email protected] Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
