From: Zbigniew Jędrzejewski-Szmek Date: Tue, 15 Mar 2022 15:35:47 +0000 (+0100) Subject: shared/install: do not try to resolve symlinks outside of root directory X-Git-Tag: v251-rc1~3^2~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=40276314afc4fb5c35c6b3da3e6185af6ed3886b;p=thirdparty%2Fsystemd.git shared/install: do not try to resolve symlinks outside of root directory I linked a file as root, so I had a symlink /root/test.service ← /etc/systemd/system/test.service. To my surpise, when running test-systemctl-enable, it failed with a cryptic EACCES. The previous commit made the logs a bit better. Strace shows that we were trying to follow the symlink without taking --root into account. It seems that this bug was introduced in 66a19d85a533b15ed32f4066ec880b5a8c06babd: before it, we'd do readlink_malloc(), which returned a path relative to root. But we only used that path for checking if the path is in remove_symlinks_to set, which contains relative paths. So if the path was relative, we'd get a false-negative answer, but we didn't go outside of the root. (We need to canonicalize the symlink to get a consistent answer.) But after 66a19 we use chase_symlinks(), without taking root into account which is completely bogus. --- diff --git a/src/shared/install.c b/src/shared/install.c index d20372cfd9c..8bb459dba74 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -611,7 +611,7 @@ static int remove_marked_symlinks_fd( return -ENOMEM; path_simplify(p); - q = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &dest, NULL); + q = chase_symlinks(p, lp->root_dir, CHASE_NONEXISTENT, &dest, NULL); if (q == -ENOENT) continue; if (q < 0) {