diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 82f6b8da2f..464384b22b 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -322,16 +322,7 @@ static int specifier_directory( if (r < 0) return r; - if (arg_root) { - _cleanup_free_ char *j = NULL; - - j = path_join(arg_root, p); - if (!j) - return -ENOMEM; - - *ret = TAKE_PTR(j); - } else - *ret = TAKE_PTR(p); + *ret = TAKE_PTR(p); return 0; } @@ -817,9 +808,14 @@ static int dir_cleanup( log_action("Would remove", "Removing", "%s directory \"%s\"", sub_path); if (!arg_dry_run && - unlinkat(dirfd(d), de->d_name, AT_REMOVEDIR) < 0 && - !IN_SET(errno, ENOENT, ENOTEMPTY)) - r = log_warning_errno(errno, "Failed to remove directory \"%s\", ignoring: %m", sub_path); + unlinkat(dirfd(d), de->d_name, AT_REMOVEDIR) < 0) { + if (errno == ENOTEMPTY) + continue; + if (errno != ENOENT) + r = log_warning_errno(errno, "Failed to remove directory \"%s\", ignoring: %m", sub_path); + } + + deleted = true; } else { _cleanup_close_ int fd = -EBADF; /* This file descriptor is defined here so that the @@ -2247,11 +2243,14 @@ 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); - 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); @@ -2689,16 +2688,30 @@ static int create_symlink(Context *c, Item *i) { assert(i); if (i->ignore_if_target_missing) { - r = chase(i->argument, arg_root, CHASE_SAFE|CHASE_PREFIX_ROOT|CHASE_NOFOLLOW, /* ret_path= */ NULL, /* ret_fd= */ NULL); + _cleanup_free_ char *target = NULL; + ChaseFlags chase_flags = CHASE_SAFE|CHASE_NOFOLLOW; + + if (!path_is_absolute(i->argument)) { + _cleanup_free_ char *dn = NULL; + + r = path_extract_directory(i->path, &dn); + if (r < 0) + return log_error_errno(r, "Failed to extract directory from path '%s': %m", i->path); + + target = path_join(dn, i->argument); + if (!target) + return log_oom(); + } else + chase_flags |= CHASE_PREFIX_ROOT; + + r = chase(target ?: i->argument, arg_root, chase_flags, /* ret_path= */ NULL, /* ret_fd= */ NULL); if (r == -ENOENT) { /* Silently skip over lines where the source file is missing. */ - log_debug_errno(r, "Symlink source path '%s/%s' does not exist, skipping line.", - strempty(arg_root), skip_leading_slash(i->argument)); + log_debug_errno(r, "Symlink source path '%s' does not exist, skipping line.", i->argument); return 0; } if (r < 0) - return log_error_errno(r, "Failed to check if symlink source path '%s/%s' exists: %m", - strempty(arg_root), skip_leading_slash(i->argument)); + return log_error_errno(r, "Failed to check if symlink source path '%s' exists: %m", i->argument); } r = path_extract_filename(i->path, &bn); @@ -4707,6 +4720,8 @@ static int read_config_file( if (candidate_item && candidate_item->age_set) { i->age = candidate_item->age; i->age_set = true; + i->age_by_file = candidate_item->age_by_file; + i->age_by_dir = candidate_item->age_by_dir; } } diff --git a/test/units/TEST-22-TMPFILES.03.sh b/test/units/TEST-22-TMPFILES.03.sh index d75294207a..390932ec97 100755 --- a/test/units/TEST-22-TMPFILES.03.sh +++ b/test/units/TEST-22-TMPFILES.03.sh @@ -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,31 @@ 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 - </tmp/ageby-x-inherit/parent/child/file +printf old >/tmp/ageby-x-inherit/parent/other/file +touch --date "3 days ago" /tmp/ageby-x-inherit/parent/child/file /tmp/ageby-x-inherit/parent/other/file + +systemd-tmpfiles --clean - <<-EOF +d /tmp/ageby-x-inherit/parent - - - m:1d +X /tmp/ageby-x-inherit/parent/child - - - - +EOF + +test ! -e /tmp/ageby-x-inherit/parent/child/file +test ! -e /tmp/ageby-x-inherit/parent/other/file +rm -rf /tmp/ageby-x-inherit diff --git a/test/units/TEST-22-TMPFILES.15.sh b/test/units/TEST-22-TMPFILES.15.sh index 14c26b8295..78be11357d 100755 --- a/test/units/TEST-22-TMPFILES.15.sh +++ b/test/units/TEST-22-TMPFILES.15.sh @@ -42,3 +42,48 @@ systemd-tmpfiles --create --root="$root" - <&1 <