tmpfiles: propagate copy errors after opening target

Opening the destination only proves that it exists. If copy_tree_at()
failed for any reason other than an existing destination, report that
copy error.

Reproducer:
  name=tmpfiles-copy-bug.$$
  src=/tmp/$name.src; dst=/tmp/$name.dst; conf=/tmp/$name.conf
  mkdir "$src" "$dst"
  printf payload >"$src/file"
  chmod 500 "$dst"
  printf 'C %s - - - - %s\n' "$dst" "$src" >"$conf"
  systemd-tmpfiles --create "$conf"

Before:
  exit=0
  copied=no

Follow-up for 8f6fb95cd0.
This commit is contained in:
dongshengyuan
2026-07-23 16:56:06 +08:00
parent 35e9ca257d
commit ac18c0569e
2 changed files with 22 additions and 0 deletions
+3
View File
@@ -2238,6 +2238,9 @@ static int copy_files(Context *c, Item *i) {
return log_error_errno(errno, "Failed to openat(%s): %m", i->path);
}
if (r < 0 && !IN_SET(r, -EEXIST, -EROFS))
return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Failed to fstat(%s): %m", i->path);
+19
View File
@@ -5,6 +5,9 @@
set -eux
set -o pipefail
# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh
rm -fr /tmp/{f,F,w}
mkdir /tmp/{f,F,w}
touch /tmp/file-owned-by-root
@@ -190,6 +193,22 @@ F /tmp/F/daemon/unsafe-symlink/exploit 0644 daemon daemon - -
EOF
test ! -e /tmp/F/daemon/unsafe-symlink/exploit
#
# 'C'
#
rm -rf /tmp/C-copy-failure-src /tmp/C-copy-failure-dst
mkdir /tmp/C-copy-failure-src /tmp/C-copy-failure-dst
printf payload >/tmp/C-copy-failure-src/file
chmod 555 /tmp/C-copy-failure-dst
(! runas nobody systemd-tmpfiles --create - <<EOF
C /tmp/C-copy-failure-dst - - - - /tmp/C-copy-failure-src
EOF
)
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
#
# 'w'
#