From: dongshengyuan <545258830@qq.com> Date: Wed, 15 Jul 2026 05:29:55 +0000 (+0800) Subject: tmpfiles: do not follow copy source symlinks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c56420a362fb5ec47105606bc1b7363951ef1698;p=thirdparty%2Fsystemd.git tmpfiles: do not follow copy source symlinks C lines copy symlinks as symlinks. The post-copy type check should inspect the source symlink itself, not follow its target. Reproducer: src=/tmp/tmpfiles-src-link.$$ dst=/tmp/tmpfiles-dst-link.$$ conf=/tmp/tmpfiles-conf.$$ ln -s missing-target "$src" printf 'C %s - - - - %s\n' "$dst" "$src" >"$conf" systemd-tmpfiles --create "$conf" Before: Failed to stat($src): No such file or directory status=73 $dst -> missing-target already existed Follow-up for 8f6fb95cd069884f4ce0a24eb20efc821ae3bc5e. --- diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 5c520ac0682..72781a49b72 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2249,8 +2249,8 @@ static int copy_files(Context *c, Item *i) { if (fstat(fd, &st) < 0) return log_error_errno(errno, "Failed to fstat(%s): %m", i->path); - if (stat(i->argument, &a) < 0) - return log_error_errno(errno, "Failed to stat(%s): %m", i->argument); + if (lstat(i->argument, &a) < 0) + return log_error_errno(errno, "Failed to lstat(%s): %m", i->argument); if (((st.st_mode ^ a.st_mode) & S_IFMT) != 0) { log_debug("Can't copy to %s, file exists already and is of different type", i->path); diff --git a/test/units/TEST-22-TMPFILES.03.sh b/test/units/TEST-22-TMPFILES.03.sh index c36f8f87905..390932ec974 100755 --- a/test/units/TEST-22-TMPFILES.03.sh +++ b/test/units/TEST-22-TMPFILES.03.sh @@ -209,6 +209,15 @@ test ! -e /tmp/C-copy-failure-dst/file chmod 755 /tmp/C-copy-failure-dst rm -rf /tmp/C-copy-failure-src /tmp/C-copy-failure-dst +rm -f /tmp/C-copy-link-src /tmp/C-copy-link-dst +ln -s missing-target /tmp/C-copy-link-src +systemd-tmpfiles --create - <