]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tmpfiles: propagate copy errors after opening target
authordongshengyuan <545258830@qq.com>
Wed, 15 Jul 2026 05:25:55 +0000 (13:25 +0800)
committerdongshengyuan <545258830@qq.com>
Thu, 23 Jul 2026 08:56:06 +0000 (16:56 +0800)
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 8f6fb95cd069884f4ce0a24eb20efc821ae3bc5e.

src/tmpfiles/tmpfiles.c
test/units/TEST-22-TMPFILES.03.sh

index 42512da6041c4fecc42144c74a52c191b676d236..9de612c1d6be6529421c08318b8e39d6a3b27372 100644 (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);
 
index d75294207aaffba1685d973f384b5dd7366332ec..c36f8f879052f22106cb65c1e8fd20ec152d9e68 100755 (executable)
@@ -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'
 #