From b1ffacb631d2209174353e35a7ff6acb35c389be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 22 Mar 2018 08:34:21 +0100 Subject: [PATCH 1/6] tests: skip udev-test when perl is not installed --- meson.build | 1 + test/meson.build | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 642ccd4491..0d62a11562 100644 --- a/meson.build +++ b/meson.build @@ -552,6 +552,7 @@ m4 = find_program('m4') stat = find_program('stat') git = find_program('git', required : false) env = find_program('env') +perl = find_program('perl', required : false) meson_make_symlink = meson.source_root() + '/tools/meson-make-symlink.sh' mkdir_p = 'mkdir -p $DESTDIR/@0@' diff --git a/test/meson.build b/test/meson.build index 99103e9570..809bd44a93 100644 --- a/test/meson.build +++ b/test/meson.build @@ -233,9 +233,13 @@ custom_target( output : 'sys', build_by_default : true) -udev_test_pl = find_program('udev-test.pl') -test('udev-test', - udev_test_pl) +if perl.found() + udev_test_pl = find_program('udev-test.pl') + test('udev-test', + udev_test_pl) +else + message('Skipping udev-test because perl is not available') +endif if conf.get('ENABLE_HWDB') == 1 hwdb_test_sh = find_program('hwdb-test.sh') From c725631f4bebe9ead39c6371431e0b6be8eab2c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 22 Mar 2018 08:42:02 +0100 Subject: [PATCH 2/6] test-execute: simplify checks if grep output is empty grep already indicates if it matched anything by return value. Additional advantage is then that if the test fails, the unexpected matching lines are visible in the log output. --- test/test-execute/exec-capabilityboundingset-invert.service | 2 +- test/test-execute/exec-privatenetwork-yes.service | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-execute/exec-capabilityboundingset-invert.service b/test/test-execute/exec-capabilityboundingset-invert.service index fd5d248702..1abe390601 100644 --- a/test/test-execute/exec-capabilityboundingset-invert.service +++ b/test/test-execute/exec-capabilityboundingset-invert.service @@ -2,6 +2,6 @@ Description=Test for CapabilityBoundingSet [Service] -ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "^Bounding set .*cap_chown"); test -z "$$c"' +ExecStart=/bin/sh -x -c '! capsh --print | grep "^Bounding set .*cap_chown"' Type=oneshot CapabilityBoundingSet=~CAP_CHOWN diff --git a/test/test-execute/exec-privatenetwork-yes.service b/test/test-execute/exec-privatenetwork-yes.service index 3df543ec93..5077f7eed2 100644 --- a/test/test-execute/exec-privatenetwork-yes.service +++ b/test/test-execute/exec-privatenetwork-yes.service @@ -2,6 +2,6 @@ Description=Test for PrivateNetwork [Service] -ExecStart=/bin/sh -x -c 'i=$$(ip link | grep ": " | grep -v ": lo:"); test -z "$$i"' +ExecStart=/bin/sh -x -c '! ip link | grep ": " | grep -v ": lo:"' Type=oneshot PrivateNetwork=yes From 6b08180ca6f1ceb913f6a69ffcaf96e9818fbdf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 22 Mar 2018 08:50:10 +0100 Subject: [PATCH 3/6] test-execute: allow sit0@ to exist in private network namespace It's always visible: $ sudo modprobe sit $ sudo unshare -n ip l 1: lo: mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000 ... 2: sit0@NONE: mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000 ... --- test/test-execute/exec-privatenetwork-yes.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-execute/exec-privatenetwork-yes.service b/test/test-execute/exec-privatenetwork-yes.service index 5077f7eed2..a38d24912f 100644 --- a/test/test-execute/exec-privatenetwork-yes.service +++ b/test/test-execute/exec-privatenetwork-yes.service @@ -2,6 +2,6 @@ Description=Test for PrivateNetwork [Service] -ExecStart=/bin/sh -x -c '! ip link | grep ": " | grep -v ": lo:"' +ExecStart=/bin/sh -x -c '! ip link | grep ": " | grep -Ev ": (lo|sit0@.*):"' Type=oneshot PrivateNetwork=yes From a5935c6601530d50016ba26c689a05928814a257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 22 Mar 2018 09:24:14 +0100 Subject: [PATCH 4/6] test-execute: skip exec-specifier-interpolation if perl is missing --- test/test-execute/exec-specifier-interpolation.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-execute/exec-specifier-interpolation.service b/test/test-execute/exec-specifier-interpolation.service index 3e62662aa9..f128e3c4b3 100644 --- a/test/test-execute/exec-specifier-interpolation.service +++ b/test/test-execute/exec-specifier-interpolation.service @@ -3,4 +3,4 @@ Description=https://github.com/systemd/systemd/issues/2637 [Service] Type=oneshot -ExecStart=/bin/sh -x -c "perl -e 'exit(!(qq{%%U} eq qq{\\x25U}))'" +ExecStart=/bin/sh -x -c "! test -x perl || perl -e 'exit(!(qq{%%U} eq qq{\\x25U}))'" From d50b5839b0d6f1e66860a6d8e125fd3fe96b76c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 22 Mar 2018 12:38:01 +0100 Subject: [PATCH 5/6] basic/mkdir: convert bool flag to enum In preparation for subsequent changes... --- src/basic/mkdir-label.c | 4 ++-- src/basic/mkdir.c | 12 +++++++----- src/basic/mkdir.h | 10 +++++++--- src/core/execute.c | 2 +- src/login/logind-dbus.c | 4 ++-- src/login/logind-inhibit.c | 4 ++-- src/login/logind-seat.c | 2 +- src/login/logind-session.c | 4 ++-- src/login/logind-user.c | 4 ++-- src/machine/machine.c | 2 +- src/network/networkd.c | 8 ++++---- src/nspawn/nspawn-setuid.c | 2 +- src/resolve/resolved.c | 2 +- src/test/test-fs-util.c | 2 +- src/timesync/timesyncd.c | 2 +- 15 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c index 6f3a46f467..2a44d276cb 100644 --- a/src/basic/mkdir-label.c +++ b/src/basic/mkdir-label.c @@ -47,8 +47,8 @@ int mkdir_label(const char *path, mode_t mode) { return mac_smack_fix(path, false, false); } -int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink) { - return mkdir_safe_internal(path, mode, uid, gid, follow_symlink, mkdir_label); +int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) { + return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_label); } int mkdir_parents_label(const char *path, mode_t mode) { diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c index de4746c867..841b5fffe5 100644 --- a/src/basic/mkdir.c +++ b/src/basic/mkdir.c @@ -31,7 +31,7 @@ #include "stat-util.h" #include "user-util.h" -int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink, mkdir_func_t _mkdir) { +int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir) { struct stat st; int r; @@ -46,14 +46,16 @@ int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, boo if (lstat(path, &st) < 0) return -errno; - if (follow_symlink && S_ISLNK(st.st_mode)) { + if ((flags & MKDIR_FOLLOW_SYMLINK) && S_ISLNK(st.st_mode)) { _cleanup_free_ char *p = NULL; r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p); if (r < 0) return r; if (r == 0) - return mkdir_safe_internal(p, mode, uid, gid, false, _mkdir); + return mkdir_safe_internal(p, mode, uid, gid, + flags & ~MKDIR_FOLLOW_SYMLINK, + _mkdir); if (lstat(p, &st) < 0) return -errno; @@ -76,8 +78,8 @@ int mkdir_errno_wrapper(const char *pathname, mode_t mode) { return 0; } -int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink) { - return mkdir_safe_internal(path, mode, uid, gid, follow_symlink, mkdir_errno_wrapper); +int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) { + return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_errno_wrapper); } int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) { diff --git a/src/basic/mkdir.h b/src/basic/mkdir.h index d6c2d579a3..2ce8bfc3e9 100644 --- a/src/basic/mkdir.h +++ b/src/basic/mkdir.h @@ -23,18 +23,22 @@ #include +typedef enum MkdirFlags { + MKDIR_FOLLOW_SYMLINK = 1 << 0, +} MkdirFlags; + int mkdir_errno_wrapper(const char *pathname, mode_t mode); -int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink); +int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); int mkdir_parents(const char *path, mode_t mode); int mkdir_p(const char *path, mode_t mode); /* mandatory access control(MAC) versions */ -int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink); +int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); int mkdir_parents_label(const char *path, mode_t mode); int mkdir_p_label(const char *path, mode_t mode); /* internally used */ typedef int (*mkdir_func_t)(const char *pathname, mode_t mode); -int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink, mkdir_func_t _mkdir); +int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir); int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir); diff --git a/src/core/execute.c b/src/core/execute.c index 7292b815db..e518606115 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2051,7 +2051,7 @@ static int setup_exec_directory( } /* First set up private root if it doesn't exist yet, with access mode 0700 and owned by root:root */ - r = mkdir_safe_label(private_root, 0700, 0, 0, false); + r = mkdir_safe_label(private_root, 0700, 0, 0, 0); if (r < 0) goto fail; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index ef5c478fef..96652eec78 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1225,7 +1225,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu mkdir_p_label("/var/lib/systemd", 0755); - r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, false); + r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, 0); if (r < 0) return r; @@ -1969,7 +1969,7 @@ static int update_schedule_file(Manager *m) { assert(m); - r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, false); + r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create shutdown subdirectory: %m"); diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index e14835292e..0c84e5ed9d 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -87,7 +87,7 @@ int inhibitor_save(Inhibitor *i) { assert(i); - r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, false); + r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, 0); if (r < 0) goto fail; @@ -291,7 +291,7 @@ int inhibitor_create_fifo(Inhibitor *i) { /* Create FIFO */ if (!i->fifo_path) { - r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, false); + r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, 0); if (r < 0) return r; diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 46e7c06ddc..69a9020876 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -95,7 +95,7 @@ int seat_save(Seat *s) { if (!s->started) return 0; - r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0, false); + r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0, 0); if (r < 0) goto fail; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 1859150b5e..b2d8c017b7 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -180,7 +180,7 @@ int session_save(Session *s) { if (!s->started) return 0; - r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, false); + r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, 0); if (r < 0) goto fail; @@ -949,7 +949,7 @@ int session_create_fifo(Session *s) { /* Create FIFO */ if (!s->fifo_path) { - r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, false); + r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, 0); if (r < 0) return r; diff --git a/src/login/logind-user.c b/src/login/logind-user.c index f85564f221..3120382481 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -143,7 +143,7 @@ static int user_save_internal(User *u) { assert(u); assert(u->state_file); - r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, false); + r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, 0); if (r < 0) goto fail; @@ -337,7 +337,7 @@ static int user_mkdir_runtime_path(User *u) { assert(u); - r = mkdir_safe_label("/run/user", 0755, 0, 0, false); + r = mkdir_safe_label("/run/user", 0755, 0, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create /run/user: %m"); diff --git a/src/machine/machine.c b/src/machine/machine.c index 4bacf91d26..51293034c1 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -131,7 +131,7 @@ int machine_save(Machine *m) { if (!m->started) return 0; - r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, false); + r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, 0); if (r < 0) goto fail; diff --git a/src/network/networkd.c b/src/network/networkd.c index 79c15d4111..1d87d5ae05 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -56,7 +56,7 @@ int main(int argc, char *argv[]) { /* Create runtime directory. This is not necessary when networkd is * started with "RuntimeDirectory=systemd/netif", or after * systemd-tmpfiles-setup.service. */ - r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid, false); + r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid, 0); if (r < 0) log_warning_errno(r, "Could not create runtime directory: %m"); @@ -75,15 +75,15 @@ int main(int argc, char *argv[]) { /* Always create the directories people can create inotify watches in. * It is necessary to create the following subdirectories after drop_privileges() * to support old kernels not supporting AmbientCapabilities=. */ - r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid, false); + r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid, 0); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'links': %m"); - r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid, false); + r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid, 0); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'leases': %m"); - r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid, false); + r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid, 0); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'lldp': %m"); diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c index 2dee5f8ec8..24f433fcbc 100644 --- a/src/nspawn/nspawn-setuid.c +++ b/src/nspawn/nspawn-setuid.c @@ -226,7 +226,7 @@ int change_uid_gid(const char *user, char **_home) { if (r < 0) return log_error_errno(r, "Failed to make home root directory: %m"); - r = mkdir_safe(home, 0755, uid, gid, false); + r = mkdir_safe(home, 0755, uid, gid, 0); if (r < 0 && r != -EEXIST) return log_error_errno(r, "Failed to make home directory: %m"); diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index a4cda0b5ef..b4c702111b 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) { } /* Always create the directory where resolv.conf will live */ - r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, false); + r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, 0); if (r < 0) { log_error_errno(r, "Could not create runtime directory: %m"); goto finish; diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index ebcec4fcc5..abd379c536 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -317,7 +317,7 @@ static void test_readlink_and_make_absolute(void) { char *r = NULL; _cleanup_free_ char *pwd = NULL; - assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), false) >= 0); + assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), 0) >= 0); assert_se(touch(name) >= 0); assert_se(symlink(name, name_alias) >= 0); diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c index 3d7cfd5be5..9ab0912463 100644 --- a/src/timesync/timesyncd.c +++ b/src/timesync/timesyncd.c @@ -71,7 +71,7 @@ static int load_clock_timestamp(uid_t uid, gid_t gid) { } } else { - r = mkdir_safe_label("/var/lib/systemd/timesync", 0755, uid, gid, true); + r = mkdir_safe_label("/var/lib/systemd/timesync", 0755, uid, gid, MKDIR_FOLLOW_SYMLINK); if (r < 0) return log_error_errno(r, "Failed to create state directory: %m"); From 37c1d5e97dbc869edd8fc178427714e2d9428d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 22 Mar 2018 13:03:41 +0100 Subject: [PATCH 6/6] tree-wide: warn when a directory path already exists but has bad mode/owner/type When we are attempting to create directory somewhere in the bowels of /var/lib and get an error that it already exists, it can be quite hard to diagnose what is wrong (especially for a user who is not aware that the directory must have the specified owner, and permissions not looser than what was requested). Let's print a warning in most cases. A warning is appropriate, because such state is usually a sign of borked installation and needs to be resolved by the adminstrator. $ build/test-fs-util Path "/tmp/test-readlink_and_make_absolute" already exists and is not a directory, refusing. (or) Directory "/tmp/test-readlink_and_make_absolute" already exists, but has mode 0775 that is too permissive (0755 was requested), refusing. (or) Directory "/tmp/test-readlink_and_make_absolute" already exists, but is owned by 1001:1000 (1000:1000 was requested), refusing. Assertion 'mkdir_safe(tempdir, 0755, getuid(), getgid(), MKDIR_WARN_MODE) >= 0' failed at ../src/test/test-fs-util.c:320, function test_readlink_and_make_absolute(). Aborting. No functional change except for the new log lines. --- src/basic/mkdir.c | 28 ++++++++++++++++++++++++---- src/basic/mkdir.h | 1 + src/core/execute.c | 2 +- src/login/logind-dbus.c | 4 ++-- src/login/logind-inhibit.c | 4 ++-- src/login/logind-seat.c | 2 +- src/login/logind-session.c | 4 ++-- src/login/logind-user.c | 4 ++-- src/machine/machine.c | 2 +- src/network/networkd.c | 8 ++++---- src/nspawn/nspawn-setuid.c | 2 +- src/resolve/resolved.c | 2 +- src/test/test-fs-util.c | 2 +- src/timesync/timesyncd.c | 3 ++- 14 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c index 841b5fffe5..cb6495525c 100644 --- a/src/basic/mkdir.c +++ b/src/basic/mkdir.c @@ -29,6 +29,7 @@ #include "mkdir.h" #include "path-util.h" #include "stat-util.h" +#include "stdio-util.h" #include "user-util.h" int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir) { @@ -61,13 +62,32 @@ int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, Mkd return -errno; } + if (!S_ISDIR(st.st_mode)) { + log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG, + "Path \"%s\" already exists and is not a directory, refusing.", path); + return -ENOTDIR; + } if ((st.st_mode & 0007) > (mode & 0007) || (st.st_mode & 0070) > (mode & 0070) || - (st.st_mode & 0700) > (mode & 0700) || - (uid != UID_INVALID && st.st_uid != uid) || - (gid != GID_INVALID && st.st_gid != gid) || - !S_ISDIR(st.st_mode)) + (st.st_mode & 0700) > (mode & 0700)) { + log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG, + "Directory \"%s\" already exists, but has mode %04o that is too permissive (%04o was requested), refusing.", + path, st.st_mode & 0777, mode); return -EEXIST; + } + if ((uid != UID_INVALID && st.st_uid != uid) || + (gid != GID_INVALID && st.st_gid != gid)) { + char u[DECIMAL_STR_MAX(uid_t)] = "-", g[DECIMAL_STR_MAX(gid_t)] = "-"; + + if (uid != UID_INVALID) + xsprintf(u, UID_FMT, uid); + if (gid != UID_INVALID) + xsprintf(g, GID_FMT, gid); + log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG, + "Directory \"%s\" already exists, but is owned by "UID_FMT":"GID_FMT" (%s:%s was requested), refusing.", + path, st.st_uid, st.st_gid, u, g); + return -EEXIST; + } return 0; } diff --git a/src/basic/mkdir.h b/src/basic/mkdir.h index 2ce8bfc3e9..59d0fb6d81 100644 --- a/src/basic/mkdir.h +++ b/src/basic/mkdir.h @@ -25,6 +25,7 @@ typedef enum MkdirFlags { MKDIR_FOLLOW_SYMLINK = 1 << 0, + MKDIR_WARN_MODE = 1 << 1, } MkdirFlags; int mkdir_errno_wrapper(const char *pathname, mode_t mode); diff --git a/src/core/execute.c b/src/core/execute.c index e518606115..7a1c3ae3ba 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2051,7 +2051,7 @@ static int setup_exec_directory( } /* First set up private root if it doesn't exist yet, with access mode 0700 and owned by root:root */ - r = mkdir_safe_label(private_root, 0700, 0, 0, 0); + r = mkdir_safe_label(private_root, 0700, 0, 0, MKDIR_WARN_MODE); if (r < 0) goto fail; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 96652eec78..a69d152b7c 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1225,7 +1225,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu mkdir_p_label("/var/lib/systemd", 0755); - r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, 0); + r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) return r; @@ -1969,7 +1969,7 @@ static int update_schedule_file(Manager *m) { assert(m); - r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, 0); + r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) return log_error_errno(r, "Failed to create shutdown subdirectory: %m"); diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index 0c84e5ed9d..f814376e80 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -87,7 +87,7 @@ int inhibitor_save(Inhibitor *i) { assert(i); - r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, 0); + r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) goto fail; @@ -291,7 +291,7 @@ int inhibitor_create_fifo(Inhibitor *i) { /* Create FIFO */ if (!i->fifo_path) { - r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, 0); + r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) return r; diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 69a9020876..adfb718eab 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -95,7 +95,7 @@ int seat_save(Seat *s) { if (!s->started) return 0; - r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0, 0); + r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) goto fail; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index b2d8c017b7..2afe422263 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -180,7 +180,7 @@ int session_save(Session *s) { if (!s->started) return 0; - r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, 0); + r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) goto fail; @@ -949,7 +949,7 @@ int session_create_fifo(Session *s) { /* Create FIFO */ if (!s->fifo_path) { - r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, 0); + r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) return r; diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 3120382481..dc8feacbf9 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -143,7 +143,7 @@ static int user_save_internal(User *u) { assert(u); assert(u->state_file); - r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, 0); + r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) goto fail; @@ -337,7 +337,7 @@ static int user_mkdir_runtime_path(User *u) { assert(u); - r = mkdir_safe_label("/run/user", 0755, 0, 0, 0); + r = mkdir_safe_label("/run/user", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) return log_error_errno(r, "Failed to create /run/user: %m"); diff --git a/src/machine/machine.c b/src/machine/machine.c index 51293034c1..95eb590f73 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -131,7 +131,7 @@ int machine_save(Machine *m) { if (!m->started) return 0; - r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, 0); + r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, MKDIR_WARN_MODE); if (r < 0) goto fail; diff --git a/src/network/networkd.c b/src/network/networkd.c index 1d87d5ae05..5fd82552ee 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -56,7 +56,7 @@ int main(int argc, char *argv[]) { /* Create runtime directory. This is not necessary when networkd is * started with "RuntimeDirectory=systemd/netif", or after * systemd-tmpfiles-setup.service. */ - r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid, 0); + r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid, MKDIR_WARN_MODE); if (r < 0) log_warning_errno(r, "Could not create runtime directory: %m"); @@ -75,15 +75,15 @@ int main(int argc, char *argv[]) { /* Always create the directories people can create inotify watches in. * It is necessary to create the following subdirectories after drop_privileges() * to support old kernels not supporting AmbientCapabilities=. */ - r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid, 0); + r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid, MKDIR_WARN_MODE); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'links': %m"); - r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid, 0); + r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid, MKDIR_WARN_MODE); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'leases': %m"); - r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid, 0); + r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid, MKDIR_WARN_MODE); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'lldp': %m"); diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c index 24f433fcbc..80189ac6db 100644 --- a/src/nspawn/nspawn-setuid.c +++ b/src/nspawn/nspawn-setuid.c @@ -227,7 +227,7 @@ int change_uid_gid(const char *user, char **_home) { return log_error_errno(r, "Failed to make home root directory: %m"); r = mkdir_safe(home, 0755, uid, gid, 0); - if (r < 0 && r != -EEXIST) + if (r < 0 && !IN_SET(r, -EEXIST, -ENOTDIR)) return log_error_errno(r, "Failed to make home directory: %m"); (void) fchown(STDIN_FILENO, uid, gid); diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index b4c702111b..193f88bd58 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) { } /* Always create the directory where resolv.conf will live */ - r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, 0); + r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, MKDIR_WARN_MODE); if (r < 0) { log_error_errno(r, "Could not create runtime directory: %m"); goto finish; diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index abd379c536..9fe79502c8 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -317,7 +317,7 @@ static void test_readlink_and_make_absolute(void) { char *r = NULL; _cleanup_free_ char *pwd = NULL; - assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), 0) >= 0); + assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), MKDIR_WARN_MODE) >= 0); assert_se(touch(name) >= 0); assert_se(symlink(name, name_alias) >= 0); diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c index 9ab0912463..7ec23904db 100644 --- a/src/timesync/timesyncd.c +++ b/src/timesync/timesyncd.c @@ -71,7 +71,8 @@ static int load_clock_timestamp(uid_t uid, gid_t gid) { } } else { - r = mkdir_safe_label("/var/lib/systemd/timesync", 0755, uid, gid, MKDIR_FOLLOW_SYMLINK); + r = mkdir_safe_label("/var/lib/systemd/timesync", 0755, uid, gid, + MKDIR_FOLLOW_SYMLINK | MKDIR_WARN_MODE); if (r < 0) return log_error_errno(r, "Failed to create state directory: %m");