diff options
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | man/systemd-analyze.xml | 7 | ||||
-rw-r--r-- | src/analyze/analyze.c | 42 | ||||
-rw-r--r-- | src/basic/log.c | 2 | ||||
-rw-r--r-- | src/fsck/fsck.c | 8 | ||||
-rw-r--r-- | src/nspawn/nspawn-mount.c | 59 | ||||
-rw-r--r-- | src/nspawn/nspawn-mount.h | 3 | ||||
-rw-r--r-- | src/nspawn/nspawn.c | 14 | ||||
-rw-r--r-- | src/shared/base-filesystem.c | 12 | ||||
-rw-r--r-- | src/shared/dropin.c | 5 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 53 |
11 files changed, 150 insertions, 60 deletions
@@ -26,13 +26,8 @@ External: Features: -* add "requires=" deps on slices from services, not just "wants=" - * add a concept of RemainAfterExit= to scope units -* add sd_booted() check into "systemctl is-system-running", and return - a new state "foreign" or so if we are not running on systemd. - * add journal vacuum by max number of files * add a new command "systemctl revert" or so, that removes all dropin diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index 198315052f..58e6fd1780 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -168,6 +168,13 @@ <option>--log-level=</option> described in <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para> + <para><command>systemd-analyze set-log-target + <replaceable>TARGET</replaceable></command> changes the current log + target of the <command>systemd</command> daemon to + <replaceable>TARGET</replaceable> (accepts the same values as + <option>--log-target=</option> described in + <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para> + <para><command>systemd-analyze verify</command> will load unit files and print warnings if any errors are detected. Files specified on the command line will be loaded, but also any other diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 7054deeae5..f05f1e5581 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -1217,10 +1217,8 @@ static int dump(sd_bus *bus, char **args) { &error, &reply, ""); - if (r < 0) { - log_error("Failed issue method call: %s", bus_error_message(&error, -r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed issue method call: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "s", &text); if (r < 0) @@ -1251,11 +1249,36 @@ static int set_log_level(sd_bus *bus, char **args) { &error, "s", args[0]); - if (r < 0) { - log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); - return -EIO; + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); + + return 0; +} + +static int set_log_target(sd_bus *bus, char **args) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(args); + + if (strv_length(args) != 1) { + log_error("This command expects one argument only."); + return -E2BIG; } + r = sd_bus_set_property( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogTarget", + &error, + "s", + args[0]); + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); + return 0; } @@ -1285,7 +1308,8 @@ static void help(void) { " critical-chain Print a tree of the time critical chain of units\n" " plot Output SVG graphic showing service initialization\n" " dot Output dependency graph in dot(1) format\n" - " set-log-level LEVEL Set logging threshold for systemd\n" + " set-log-level LEVEL Set logging threshold for manager\n" + " set-log-target TARGET Set logging target for manager\n" " dump Output state serialization of service manager\n" " verify FILE... Check unit files for correctness\n" , program_invocation_short_name); @@ -1452,6 +1476,8 @@ int main(int argc, char *argv[]) { r = dump(bus, argv+optind+1); else if (streq(argv[optind], "set-log-level")) r = set_log_level(bus, argv+optind+1); + else if (streq(argv[optind], "set-log-target")) + r = set_log_target(bus, argv+optind+1); else log_error("Unknown operation '%s'.", argv[optind]); } diff --git a/src/basic/log.c b/src/basic/log.c index 38f42b3a6e..e6d7d15182 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -922,7 +922,7 @@ int log_set_max_level_from_string(const char *e) { t = log_level_from_string(e); if (t < 0) - return t; + return -EINVAL; log_set_max_level(t); return 0; diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 8e790b85ae..30c846f01d 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -60,7 +60,7 @@ static bool arg_force = false; static bool arg_show_progress = false; static const char *arg_repair = "-a"; -static void start_target(const char *target) { +static void start_target(const char *target, const char *mode) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; int r; @@ -83,7 +83,7 @@ static void start_target(const char *target) { "StartUnitReplace", &error, NULL, - "sss", "basic.target", target, "replace"); + "sss", "basic.target", target, mode); /* Don't print a warning if we aren't called during startup */ if (r < 0 && !sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_JOB)) @@ -463,10 +463,10 @@ int main(int argc, char *argv[]) { if (status.si_code == CLD_EXITED && (status.si_status & FSCK_SYSTEM_SHOULD_REBOOT) && root_directory) /* System should be rebooted. */ - start_target(SPECIAL_REBOOT_TARGET); + start_target(SPECIAL_REBOOT_TARGET, "replace-irreversibly"); else if (status.si_code == CLD_EXITED && (status.si_status & (FSCK_SYSTEM_SHOULD_REBOOT | FSCK_ERRORS_LEFT_UNCORRECTED))) /* Some other problem */ - start_target(SPECIAL_EMERGENCY_TARGET); + start_target(SPECIAL_EMERGENCY_TARGET, "replace"); else { log_warning("Ignoring error."); r = 0; diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 2bca39f45d..3d302ef9ad 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -216,8 +216,55 @@ static int tmpfs_patch_options( return !!buf; } +int mount_sysfs(const char *dest) { + const char *full, *top, *x; + + top = prefix_roota(dest, "/sys"); + full = prefix_roota(top, "/full"); + + (void) mkdir(full, 0755); + + if (mount("sysfs", full, "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0) + return log_error_errno(errno, "Failed to mount sysfs to %s: %m", full); + + FOREACH_STRING(x, "block", "bus", "class", "dev", "devices", "kernel") { + _cleanup_free_ char *from = NULL, *to = NULL; + + from = prefix_root(full, x); + if (!from) + return log_oom(); + + to = prefix_root(top, x); + if (!to) + return log_oom(); + + (void) mkdir(to, 0755); + + if (mount(from, to, NULL, MS_BIND, NULL) < 0) + return log_error_errno(errno, "Failed to mount /sys/%s into place: %m", x); + + if (mount(NULL, to, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0) + return log_error_errno(errno, "Failed to mount /sys/%s read-only: %m", x); + } + + if (umount(full) < 0) + return log_error_errno(errno, "Failed to unmount %s: %m", full); + + if (rmdir(full) < 0) + return log_error_errno(errno, "Failed to remove %s: %m", full); + + x = prefix_roota(top, "/fs/kdbus"); + (void) mkdir(x, 0755); + + if (mount(NULL, top, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0) + return log_error_errno(errno, "Failed to make %s read-only: %m", top); + + return 0; +} + int mount_all(const char *dest, - bool userns, uid_t uid_shift, uid_t uid_range, + bool use_userns, bool in_userns, + uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { typedef struct MountPoint { @@ -234,7 +281,7 @@ int mount_all(const char *dest, { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true }, { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true }, /* Bind mount first */ { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true }, /* Then, make it r/o */ - { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false }, + { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false }, { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false }, { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false }, { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false }, @@ -252,7 +299,7 @@ int mount_all(const char *dest, _cleanup_free_ char *where = NULL, *options = NULL; const char *o; - if (userns != mount_table[k].userns) + if (in_userns != mount_table[k].userns) continue; where = prefix_root(dest, mount_table[k].where); @@ -278,7 +325,7 @@ int mount_all(const char *dest, o = mount_table[k].options; if (streq_ptr(mount_table[k].type, "tmpfs")) { - r = tmpfs_patch_options(o, userns, uid_shift, uid_range, selinux_apifs_context, &options); + r = tmpfs_patch_options(o, use_userns, uid_shift, uid_range, selinux_apifs_context, &options); if (r < 0) return log_oom(); if (r > 0) @@ -534,7 +581,7 @@ static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controlle char *to; int r; - to = strjoina(dest, "/sys/fs/cgroup/", hierarchy); + to = strjoina(strempty(dest), "/sys/fs/cgroup/", hierarchy); r = path_is_mount_point(to, 0); if (r < 0 && r != -ENOENT) @@ -569,6 +616,8 @@ static int mount_legacy_cgroups( cgroup_root = prefix_roota(dest, "/sys/fs/cgroup"); + (void) mkdir_p(cgroup_root, 0755); + /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */ r = path_is_mount_point(cgroup_root, AT_SYMLINK_FOLLOW); if (r < 0) diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index 5abd44cc4b..54cab87665 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -57,7 +57,8 @@ int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s); int custom_mount_compare(const void *a, const void *b); -int mount_all(const char *dest, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); +int mount_all(const char *dest, bool use_userns, bool in_userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); +int mount_sysfs(const char *dest); int mount_cgroups(const char *dest, bool unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); int mount_systemd_cgroup_writable(const char *dest, bool unified_requested); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 16dfe8a7c1..f4a2e3d9ba 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -83,12 +83,12 @@ #include "udev-util.h" #include "util.h" -#include "nspawn-settings.h" +#include "nspawn-cgroup.h" +#include "nspawn-expose-ports.h" #include "nspawn-mount.h" #include "nspawn-network.h" -#include "nspawn-expose-ports.h" -#include "nspawn-cgroup.h" #include "nspawn-register.h" +#include "nspawn-settings.h" #include "nspawn-setuid.h" typedef enum ContainerStatus { @@ -2450,7 +2450,11 @@ static int inner_child( } } - r = mount_all(NULL, true, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); + r = mount_all(NULL, arg_userns, true, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); + if (r < 0) + return r; + + r = mount_sysfs(NULL); if (r < 0) return r; @@ -2701,7 +2705,7 @@ static int outer_child( return log_error_errno(r, "Failed to make tree read-only: %m"); } - r = mount_all(directory, false, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); + r = mount_all(directory, arg_userns, false, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); if (r < 0) return r; diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c index ab6fc171b0..48492ed13d 100644 --- a/src/shared/base-filesystem.c +++ b/src/shared/base-filesystem.c @@ -34,12 +34,13 @@ typedef struct BaseFilesystem { mode_t mode; const char *target; const char *exists; + bool ignore_failure; } BaseFilesystem; static const BaseFilesystem table[] = { { "bin", 0, "usr/bin\0", NULL }, { "lib", 0, "usr/lib\0", NULL }, - { "root", 0755, NULL, NULL }, + { "root", 0755, NULL, NULL, true }, { "sbin", 0, "usr/sbin\0", NULL }, { "usr", 0755, NULL, NULL }, { "var", 0755, NULL, NULL }, @@ -104,8 +105,13 @@ int base_filesystem_create(const char *root, uid_t uid, gid_t gid) { RUN_WITH_UMASK(0000) r = mkdirat(fd, table[i].dir, table[i].mode); - if (r < 0 && errno != EEXIST) - return log_error_errno(errno, "Failed to create directory at %s/%s: %m", root, table[i].dir); + if (r < 0 && errno != EEXIST) { + log_full_errno(table[i].ignore_failure ? LOG_DEBUG : LOG_ERR, errno, + "Failed to create directory at %s/%s: %m", root, table[i].dir); + + if (!table[i].ignore_failure) + return -errno; + } if (uid != UID_INVALID || gid != UID_INVALID) { if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0) diff --git a/src/shared/dropin.c b/src/shared/dropin.c index 963d05d32e..1845068adb 100644 --- a/src/shared/dropin.c +++ b/src/shared/dropin.c @@ -78,7 +78,7 @@ int write_drop_in(const char *dir, const char *unit, unsigned level, if (r < 0) return r; - mkdir_p(p, 0755); + (void) mkdir_p(p, 0755); return write_string_file_atomic_label(q, data); } @@ -132,8 +132,7 @@ static int iterate_dir( if (errno == ENOENT) return 0; - log_error_errno(errno, "Failed to open directory %s: %m", path); - return -errno; + return log_error_errno(errno, "Failed to open directory %s: %m", path); } for (;;) { diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 9718ef54df..a965369c0c 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5907,7 +5907,7 @@ static int is_system_running(int argc, char *argv[], void *userdata) { } static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) { - char *t; + _cleanup_free_ char *t = NULL; int r; assert(new_path); @@ -5919,26 +5919,21 @@ static int create_edit_temp_file(const char *new_path, const char *original_path return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path); r = mkdir_parents(new_path, 0755); - if (r < 0) { - free(t); + if (r < 0) return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path); - } r = copy_file(original_path, t, 0, 0644, 0); if (r == -ENOENT) { + r = touch(t); - if (r < 0) { - log_error_errno(r, "Failed to create temporary file \"%s\": %m", t); - free(t); - return r; - } - } else if (r < 0) { - log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t); - free(t); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t); + + } else if (r < 0) + return log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t); *ret_tmp_fn = t; + t = NULL; return 0; } @@ -5946,6 +5941,9 @@ static int create_edit_temp_file(const char *new_path, const char *original_path static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) { _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL; + assert(name); + assert(ret_path); + switch (arg_scope) { case UNIT_FILE_SYSTEM: path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name); @@ -5997,8 +5995,7 @@ static int get_file_to_edit(const char *name, const char *user_home, const char } static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) { - char *tmp_new_path, *ending; - char *tmp_tmp_path; + char *tmp_new_path, *tmp_tmp_path, *ending; int r; assert(unit_name); @@ -6030,8 +6027,7 @@ static int unit_file_create_copy( char **ret_new_path, char **ret_tmp_path) { - char *tmp_new_path; - char *tmp_tmp_path; + char *tmp_new_path, *tmp_tmp_path; int r; assert(fragment_path); @@ -6150,7 +6146,7 @@ static int run_editor(char **paths) { if (r < 0) return log_error_errno(r, "Failed to wait for child: %m"); - return r; + return 0; } static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { @@ -6234,13 +6230,14 @@ static int edit(int argc, char *argv[], void *userdata) { goto end; STRV_FOREACH_PAIR(original, tmp, paths) { - /* If the temporary file is empty we ignore it. - * It's useful if the user wants to cancel its modification + /* If the temporary file is empty we ignore it. It's + * useful if the user wants to cancel its modification */ if (null_or_empty_path(*tmp)) { - log_warning("Editing \"%s\" canceled: temporary file is empty", *original); + log_warning("Editing \"%s\" canceled: temporary file is empty.", *original); continue; } + r = rename(*tmp, *original); if (r < 0) { r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original); @@ -6248,12 +6245,14 @@ static int edit(int argc, char *argv[], void *userdata) { } } - if (!arg_no_reload && bus && !install_client_side()) + r = 0; + + if (!arg_no_reload && !install_client_side()) r = daemon_reload(argc, argv, userdata); end: STRV_FOREACH_PAIR(original, tmp, paths) - unlink_noerrno(*tmp); + (void) unlink(*tmp); return r; } @@ -7004,7 +7003,7 @@ static int shutdown_parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "HPrhkKtafFc", options, NULL)) >= 0) switch (c) { case ARG_HELP: @@ -7487,6 +7486,10 @@ static int logind_schedule_shutdown(void) { case ACTION_KEXEC: action = "kexec"; break; + case ACTION_EXIT: + action = "exit"; + break; + case ACTION_REBOOT: default: action = "reboot"; break; |