1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-23 17:34:00 +03:00

Merge pull request #11820 from dm0-/chase

Allow tmpfiles to create files in a root under an unprivileged directory
This commit is contained in:
Lennart Poettering 2019-03-04 13:04:45 +01:00 committed by GitHub
commit 46d4d67d79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 3 deletions

View File

@ -926,6 +926,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (fstat(child, &st) < 0)
return -errno;
if ((flags & CHASE_SAFE) &&
(empty_or_root(root) || (size_t)(todo - buffer) > strlen(root)) &&
unsafe_transition(&previous_stat, &st))
return log_unsafe_transition(fd, child, path, flags);

View File

@ -154,6 +154,30 @@ static void test_chase_symlinks(void) {
assert_se(path_equal(result, q));
result = mfree(result);
/* Paths underneath the "root" with different UIDs while using CHASE_SAFE */
if (geteuid() == 0) {
p = strjoina(temp, "/user");
assert_se(mkdir(p, 0755) >= 0);
assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0);
q = strjoina(temp, "/user/root");
assert_se(mkdir(q, 0755) >= 0);
p = strjoina(q, "/link");
assert_se(symlink("/", p) >= 0);
/* Fail when user-owned directories contain root-owned subdirectories. */
r = chase_symlinks(p, temp, CHASE_SAFE, &result);
assert_se(r == -ENOLINK);
result = mfree(result);
/* Allow this when the user-owned directories are all in the "root". */
r = chase_symlinks(p, q, CHASE_SAFE, &result);
assert_se(r > 0);
result = mfree(result);
}
/* Paths using . */
r = chase_symlinks("/etc/./.././", NULL, 0, &result);

View File

@ -856,7 +856,7 @@ static int path_open_parent_safe(const char *path) {
if (!dn)
return log_oom();
fd = chase_symlinks(dn, NULL, CHASE_OPEN|CHASE_SAFE|CHASE_WARN, NULL);
fd = chase_symlinks(dn, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN, NULL);
if (fd < 0 && fd != -ENOLINK)
return log_error_errno(fd, "Failed to validate path %s: %m", path);
@ -877,7 +877,7 @@ static int path_open_safe(const char *path) {
"Failed to open invalid path '%s'.",
path);
fd = chase_symlinks(path, NULL, CHASE_OPEN|CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL);
fd = chase_symlinks(path, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL);
if (fd < 0 && fd != -ENOLINK)
return log_error_errno(fd, "Failed to validate path %s: %m", path);
@ -2256,7 +2256,7 @@ static int process_item(Item *i, OperationMask operation) {
i->done |= operation;
r = chase_symlinks(i->path, NULL, CHASE_NO_AUTOFS|CHASE_WARN, NULL);
r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL);
if (r == -EREMOTE) {
log_notice_errno(r, "Skipping %s", i->path);
return 0;

View File

@ -0,0 +1,32 @@
#! /bin/bash
#
# Verify tmpfiles can run in a root directory under a path prefix that contains
# directories owned by unprivileged users, for example when a root file system
# is mounted in a regular user's home directory.
#
# https://github.com/systemd/systemd/pull/11820
#
set -e
rm -fr /tmp/root /tmp/user
mkdir -p /tmp/root /tmp/user/root
chown daemon:daemon /tmp/user
# Verify the command works as expected with no prefix or a root-owned prefix.
echo 'd /tmp/root/test1' | systemd-tmpfiles --create -
test -d /tmp/root/test1
echo 'd /test2' | systemd-tmpfiles --root=/tmp/root --create -
test -d /tmp/root/test2
# Verify the command fails to write to a root-owned subdirectory under an
# unprivileged user's directory when it's not part of the prefix, as expected
# by the unsafe_transition function.
! echo 'd /tmp/user/root/test' | systemd-tmpfiles --create -
! test -e /tmp/user/root/test
! echo 'd /user/root/test' | systemd-tmpfiles --root=/tmp --create -
! test -e /tmp/user/root/test
# Verify the above works when all user-owned directories are in the prefix.
echo 'd /test' | systemd-tmpfiles --root=/tmp/user/root --create -
test -d /tmp/user/root/test