diff options
Diffstat (limited to 'src')
30 files changed, 389 insertions, 276 deletions
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index d2d18f13f0..6948ed3931 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -182,8 +182,7 @@ int cg_read_subgroup(DIR *d, char **fn) { if (de->d_type != DT_DIR) continue; - if (streq(de->d_name, ".") || - streq(de->d_name, "..")) + if (dot_or_dot_dot(de->d_name)) continue; b = strdup(de->d_name); diff --git a/src/basic/copy.c b/src/basic/copy.c index 9883f5fa31..e9a7efd232 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -331,7 +331,7 @@ static int fd_copy_directory( struct stat buf; int q; - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) { diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c index 6843aedd0a..2d6e377f0a 100644 --- a/src/basic/hexdecoct.c +++ b/src/basic/hexdecoct.c @@ -72,10 +72,10 @@ int unhexchar(char c) { } char *hexmem(const void *p, size_t l) { - char *r, *z; const uint8_t *x; + char *r, *z; - z = r = malloc(l * 2 + 1); + z = r = new(char, l * 2 + 1); if (!r) return NULL; diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 9a51e0d8bc..1313a52c9c 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -699,10 +699,7 @@ bool filename_is_valid(const char *p) { if (isempty(p)) return false; - if (streq(p, ".")) - return false; - - if (streq(p, "..")) + if (dot_or_dot_dot(p)) return false; e = strchrnul(p, '/'); @@ -720,14 +717,17 @@ bool path_is_safe(const char *p) { if (isempty(p)) return false; - if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../")) + if (dot_or_dot_dot(p)) + return false; + + if (startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../")) return false; if (strlen(p)+1 > PATH_MAX) return false; /* The following two checks are not really dangerous, but hey, they still are confusing */ - if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./")) + if (startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./")) return false; if (strstr(p, "//")) @@ -892,3 +892,16 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version) return false; } + +bool dot_or_dot_dot(const char *path) { + if (!path) + return false; + if (path[0] != '.') + return false; + if (path[1] == 0) + return true; + if (path[1] != '.') + return false; + + return path[2] == 0; +} diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 349cdac7d6..35aef3adc8 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -141,3 +141,5 @@ bool is_device_path(const char *path); bool is_deviceallow_pattern(const char *path); int systemd_installation_has_version(const char *root, unsigned minimal_version); + +bool dot_or_dot_dot(const char *path); diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c index 07d42f78dd..08497af729 100644 --- a/src/basic/rm-rf.c +++ b/src/basic/rm-rf.c @@ -83,7 +83,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { bool is_dir; struct stat st; - if (streq(de->d_name, ".") || streq(de->d_name, "..")) + if (dot_or_dot_dot(de->d_name)) continue; if (de->d_type == DT_UNKNOWN || diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 77f81a60ba..17e90a8994 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -877,7 +877,7 @@ bool ifname_valid(const char *p) { if (strlen(p) >= IFNAMSIZ) return false; - if (STR_IN_SET(p, ".", "..")) + if (dot_or_dot_dot(p)) return false; while (*p) { diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 44ea6215dc..7cc54a8cdd 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -1647,7 +1647,7 @@ static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, con loaded_image->LoadOptionsSize = (StrLen(loaded_image->LoadOptions)+1) * sizeof(CHAR16); #ifdef SD_BOOT_LOG_TPM - /* Try to log any options to the TPM, escpecially to catch manually edited options */ + /* Try to log any options to the TPM, especially to catch manually edited options */ err = tpm_log_event(SD_TPM_PCR, (EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions, loaded_image->LoadOptionsSize, loaded_image->LoadOptions); diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 1e250f34f4..7c1ffb1bca 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -100,7 +100,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { cmdline = line; #ifdef SD_BOOT_LOG_TPM - /* Try to log any options to the TPM, escpecially manually edited options */ + /* Try to log any options to the TPM, especially manually edited options */ err = tpm_log_event(SD_TPM_PCR, (EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions, loaded_image->LoadOptionsSize, loaded_image->LoadOptions); diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index b55aa86a40..82b4d9ccb3 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -26,7 +26,6 @@ #include "sd-bus.h" #include "alloc-util.h" -#include "bus-error.h" #include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" @@ -35,12 +34,21 @@ #include "output-mode.h" #include "pager.h" #include "path-util.h" +#include "strv.h" #include "unit-name.h" #include "util.h" static bool arg_no_pager = false; static bool arg_kernel_threads = false; static bool arg_all = false; + +static enum { + SHOW_UNIT_NONE, + SHOW_UNIT_SYSTEM, + SHOW_UNIT_USER, +} arg_show_unit = SHOW_UNIT_NONE; +static char **arg_names = NULL; + static int arg_full = -1; static char* arg_machine = NULL; @@ -51,6 +59,8 @@ static void help(void) { " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " -a --all Show all groups, including empty\n" + " -u --unit Show the subtrees of specifified system units\n" + " --user-unit Show the subtrees of specifified user units\n" " -l --full Do not ellipsize output\n" " -k Include kernel threads in output\n" " -M --machine= Show container\n" @@ -62,15 +72,18 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_NO_PAGER = 0x100, ARG_VERSION, + ARG_USER_UNIT, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "all", no_argument, NULL, 'a' }, - { "full", no_argument, NULL, 'l' }, - { "machine", required_argument, NULL, 'M' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "all", no_argument, NULL, 'a' }, + { "full", no_argument, NULL, 'l' }, + { "machine", required_argument, NULL, 'M' }, + { "unit", optional_argument, NULL, 'u' }, + { "user-unit", optional_argument, NULL, ARG_USER_UNIT }, {} }; @@ -79,7 +92,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 1); assert(argv); - while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "-hkalM:u::", options, NULL)) >= 0) switch (c) { @@ -98,6 +111,24 @@ static int parse_argv(int argc, char *argv[]) { arg_all = true; break; + case 'u': + arg_show_unit = SHOW_UNIT_SYSTEM; + if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */ + return log_oom(); + break; + + case ARG_USER_UNIT: + arg_show_unit = SHOW_UNIT_USER; + if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */ + return log_oom(); + break; + + case 1: + /* positional argument */ + if (strv_push(&arg_names, optarg) < 0) + return log_oom(); + break; + case 'l': arg_full = true; break; @@ -117,51 +148,12 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - return 1; -} - -static int get_cgroup_root(char **ret) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ char *unit = NULL, *path = NULL; - const char *m; - int r; - - if (!arg_machine) { - r = cg_get_root_path(ret); - if (r == -ENOMEDIUM) - return log_error_errno(r, "Failed to get root control group path: No cgroup filesystem mounted on /sys/fs/cgroup"); - else if (r < 0) - return log_error_errno(r, "Failed to get root control group path: %m"); - - return 0; + if (arg_machine && arg_show_unit != SHOW_UNIT_NONE) { + log_error("Cannot combine --unit or --user-unit with --machine."); + return -EINVAL; } - m = strjoina("/run/systemd/machines/", arg_machine); - r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); - if (r < 0) - return log_error_errno(r, "Failed to load machine data: %m"); - - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); - if (r < 0) - return log_error_errno(r, "Failed to create bus connection: %m"); - - r = sd_bus_get_property_string( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - ret); - if (r < 0) - return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r)); - - return 0; + return 1; } static void show_cg_info(const char *controller, const char *path) { @@ -194,31 +186,65 @@ int main(int argc, char *argv[]) { (arg_full > 0) * OUTPUT_FULL_WIDTH | arg_kernel_threads * OUTPUT_KERNEL_THREADS; - if (optind < argc) { + if (arg_names) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *root = NULL; - int i; + char **name; - r = get_cgroup_root(&root); - if (r < 0) - goto finish; - - for (i = optind; i < argc; i++) { + STRV_FOREACH(name, arg_names) { int q; - if (path_startswith(argv[i], "/sys/fs/cgroup")) { + if (arg_show_unit != SHOW_UNIT_NONE) { + /* Command line arguments are unit names */ + _cleanup_free_ char *cgroup = NULL; + + if (!bus) { + /* Connect to the bus only if necessary */ + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, + arg_show_unit == SHOW_UNIT_USER, + &bus); + if (r < 0) { + log_error_errno(r, "Failed to create bus connection: %m"); + goto finish; + } + } + + q = show_cgroup_get_unit_path_and_warn(bus, *name, &cgroup); + if (q < 0) + goto failed; + + if (isempty(cgroup)) { + log_warning("Unit %s not found.", *name); + q = -ENOENT; + goto failed; + } + + printf("Unit %s (%s):\n", *name, cgroup); + fflush(stdout); + + q = show_cgroup_by_path(cgroup, NULL, 0, output_flags); - printf("Directory %s:\n", argv[i]); + } else if (path_startswith(*name, "/sys/fs/cgroup")) { + + printf("Directory %s:\n", *name); fflush(stdout); - q = show_cgroup_by_path(argv[i], NULL, 0, output_flags); + q = show_cgroup_by_path(*name, NULL, 0, output_flags); } else { _cleanup_free_ char *c = NULL, *p = NULL, *j = NULL; const char *controller, *path; - r = cg_split_spec(argv[i], &c, &p); + if (!root) { + /* Query root only if needed, treat error as fatal */ + r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); + if (r < 0) + goto finish; + } + + r = cg_split_spec(*name, &c, &p); if (r < 0) { - log_error_errno(r, "Failed to split argument %s: %m", argv[i]); - goto finish; + log_error_errno(r, "Failed to split argument %s: %m", *name); + goto failed; } controller = c ?: SYSTEMD_CGROUP_CONTROLLER; @@ -239,7 +265,8 @@ int main(int argc, char *argv[]) { q = show_cgroup(controller, path, NULL, 0, output_flags); } - if (q < 0) + failed: + if (q < 0 && r >= 0) r = q; } @@ -267,7 +294,7 @@ int main(int argc, char *argv[]) { if (!done) { _cleanup_free_ char *root = NULL; - r = get_cgroup_root(&root); + r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); if (r < 0) goto finish; @@ -283,6 +310,7 @@ int main(int argc, char *argv[]) { finish: pager_close(); + free(arg_names); /* don't free the strings */ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index af5c3d8695..50ac6a58b0 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -31,6 +31,7 @@ #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" +#include "cgroup-show.h" #include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" @@ -862,13 +863,9 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - if (optind == argc-1) { - if (arg_machine) { - log_error("Specifying a control group path together with the -M option is not allowed"); - return -EINVAL; - } + if (optind == argc - 1) arg_root = argv[optind]; - } else if (optind < argc) { + else if (optind < argc) { log_error("Too many arguments."); return -EINVAL; } @@ -890,59 +887,6 @@ static const char* counting_what(void) { return "userspace processes (excl. kernel)"; } -static int get_cgroup_root(char **ret) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ char *unit = NULL, *path = NULL; - const char *m; - int r; - - if (arg_root) { - char *aux; - - aux = strdup(arg_root); - if (!aux) - return log_oom(); - - *ret = aux; - return 0; - } - - if (!arg_machine) { - r = cg_get_root_path(ret); - if (r < 0) - return log_error_errno(r, "Failed to get root control group path: %m"); - - return 0; - } - - m = strjoina("/run/systemd/machines/", arg_machine); - r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); - if (r < 0) - return log_error_errno(r, "Failed to load machine data: %m"); - - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); - if (r < 0) - return log_error_errno(r, "Failed to create bus connection: %m"); - - r = sd_bus_get_property_string( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - ret); - if (r < 0) - return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r)); - - return 0; -} - int main(int argc, char *argv[]) { int r; Hashmap *a = NULL, *b = NULL; @@ -967,11 +911,12 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = get_cgroup_root(&root); + r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root); if (r < 0) { log_error_errno(r, "Failed to get root control group path: %m"); goto finish; - } + } else + log_debug("Cgroup path: %s", root); a = hashmap_new(&string_hash_ops); b = hashmap_new(&string_hash_ops); diff --git a/src/core/execute.c b/src/core/execute.c index d0faba5a85..47cc4311c1 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1685,25 +1685,31 @@ static int setup_private_users(uid_t uid, gid_t gid) { * child then writes the UID mapping, under full privileges. The parent waits for the child to finish and * continues execution normally. */ - if (uid != 0 && uid_is_valid(uid)) - asprintf(&uid_map, - "0 0 1\n" /* Map root → root */ - UID_FMT " " UID_FMT " 1\n", /* Map $UID → $UID */ - uid, uid); - else + if (uid != 0 && uid_is_valid(uid)) { + r = asprintf(&uid_map, + "0 0 1\n" /* Map root → root */ + UID_FMT " " UID_FMT " 1\n", /* Map $UID → $UID */ + uid, uid); + if (r < 0) + return -ENOMEM; + } else { uid_map = strdup("0 0 1\n"); /* The case where the above is the same */ - if (!uid_map) - return -ENOMEM; + if (!uid_map) + return -ENOMEM; + } - if (gid != 0 && gid_is_valid(gid)) - asprintf(&gid_map, - "0 0 1\n" /* Map root → root */ - GID_FMT " " GID_FMT " 1\n", /* Map $GID → $GID */ - gid, gid); - else + if (gid != 0 && gid_is_valid(gid)) { + r = asprintf(&gid_map, + "0 0 1\n" /* Map root → root */ + GID_FMT " " GID_FMT " 1\n", /* Map $GID → $GID */ + gid, gid); + if (r < 0) + return -ENOMEM; + } else { gid_map = strdup("0 0 1\n"); /* The case where the above is the same */ - if (!gid_map) - return -ENOMEM; + if (!gid_map) + return -ENOMEM; + } /* Create a communication channel so that the parent can tell the child when it finished creating the user * namespace. */ @@ -3096,7 +3102,7 @@ const char* exec_context_fdname(const ExecContext *c, int fd_index) { int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]) { unsigned i, targets; - const char *stdio_fdname[3]; + const char* stdio_fdname[3]; assert(c); assert(p); @@ -3109,18 +3115,32 @@ int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParamet stdio_fdname[i] = exec_context_fdname(c, i); for (i = 0; i < p->n_fds && targets > 0; i++) - if (named_iofds[STDIN_FILENO] < 0 && c->std_input == EXEC_INPUT_NAMED_FD && stdio_fdname[STDIN_FILENO] && streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) { + if (named_iofds[STDIN_FILENO] < 0 && + c->std_input == EXEC_INPUT_NAMED_FD && + stdio_fdname[STDIN_FILENO] && + streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) { + named_iofds[STDIN_FILENO] = p->fds[i]; targets--; - } else if (named_iofds[STDOUT_FILENO] < 0 && c->std_output == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDOUT_FILENO] && streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) { + + } else if (named_iofds[STDOUT_FILENO] < 0 && + c->std_output == EXEC_OUTPUT_NAMED_FD && + stdio_fdname[STDOUT_FILENO] && + streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) { + named_iofds[STDOUT_FILENO] = p->fds[i]; targets--; - } else if (named_iofds[STDERR_FILENO] < 0 && c->std_error == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDERR_FILENO] && streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) { + + } else if (named_iofds[STDERR_FILENO] < 0 && + c->std_error == EXEC_OUTPUT_NAMED_FD && + stdio_fdname[STDERR_FILENO] && + streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) { + named_iofds[STDERR_FILENO] = p->fds[i]; targets--; } - return (targets == 0 ? 0 : -ENOENT); + return targets == 0 ? 0 : -ENOENT; } int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) { diff --git a/src/core/killall.c b/src/core/killall.c index b3aa22adc5..7a9df546ee 100644 --- a/src/core/killall.c +++ b/src/core/killall.c @@ -66,29 +66,26 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) { if (count <= 0) return true; - /* Processes with argv[0][0] = '@' we ignore from the killing - * spree. + /* Processes with argv[0][0] = '@' we ignore from the killing spree. * * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */ - if (c == '@' && warn_rootfs) { - _cleanup_free_ char *comm = NULL; + if (c != '@') + return false; - r = pid_from_same_root_fs(pid); - if (r < 0) - return true; + if (warn_rootfs && + pid_from_same_root_fs(pid) == 0) { + + _cleanup_free_ char *comm = NULL; get_process_comm(pid, &comm); - if (r) - log_notice("Process " PID_FMT " (%s) has been marked to be excluded from killing. It is " - "running from the root file system, and thus likely to block re-mounting of the " - "root file system to read-only. Please consider moving it into an initrd file " - "system instead.", pid, strna(comm)); - return true; - } else if (c == '@') - return true; + log_notice("Process " PID_FMT " (%s) has been marked to be excluded from killing. It is " + "running from the root file system, and thus likely to block re-mounting of the " + "root file system to read-only. Please consider moving it into an initrd file " + "system instead.", pid, strna(comm)); + } - return false; + return true; } static void wait_for_children(Set *pids, sigset_t *mask) { diff --git a/src/core/timer.c b/src/core/timer.c index 5ee14669d2..d7441d638f 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -232,7 +232,7 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) { if (v->base == TIMER_CALENDAR) { _cleanup_free_ char *p = NULL; - calendar_spec_to_string(v->calendar_spec, &p); + (void) calendar_spec_to_string(v->calendar_spec, &p); fprintf(f, "%s%s: %s\n", diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index cefd1b85df..91c653312a 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -594,7 +594,7 @@ static int help(void) { int main(int argc, char *argv[]) { struct crypt_device *cd = NULL; - int r; + int r = -EINVAL; if (argc <= 1) { r = help(); @@ -603,7 +603,6 @@ int main(int argc, char *argv[]) { if (argc < 3) { log_error("This program requires at least two arguments."); - r = -EINVAL; goto finish; } @@ -750,7 +749,6 @@ int main(int argc, char *argv[]) { } else { log_error("Unknown verb %s.", argv[1]); - r = -EINVAL; goto finish; } diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index e61ef8f249..b958070c90 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -658,7 +658,7 @@ static int get_block_device_harder(const char *path, dev_t *dev) { FOREACH_DIRENT_ALL(de, d, return -errno) { - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN)) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 93b9ff2da0..ef87b176fa 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -42,6 +42,7 @@ #include "sd-event.h" #include "set.h" #include "string-util.h" +#include "strv.h" #include "xattr-util.h" #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem)) @@ -507,42 +508,58 @@ static int journal_file_refresh_header(JournalFile *f) { return r; } -static int journal_file_verify_header(JournalFile *f) { +static bool warn_wrong_flags(const JournalFile *f, bool compatible) { + const uint32_t any = compatible ? HEADER_COMPATIBLE_ANY : HEADER_INCOMPATIBLE_ANY, + supported = compatible ? HEADER_COMPATIBLE_SUPPORTED : HEADER_INCOMPATIBLE_SUPPORTED; + const char *type = compatible ? "compatible" : "incompatible"; uint32_t flags; + flags = le32toh(compatible ? f->header->compatible_flags : f->header->incompatible_flags); + + if (flags & ~supported) { + if (flags & ~any) + log_debug("Journal file %s has unknown %s flags 0x%"PRIx32, + f->path, type, flags & ~any); + flags = (flags & any) & ~supported; + if (flags) { + const char* strv[3]; + unsigned n = 0; + _cleanup_free_ char *t = NULL; + + if (compatible && (flags & HEADER_COMPATIBLE_SEALED)) + strv[n++] = "sealed"; + if (!compatible && (flags & HEADER_INCOMPATIBLE_COMPRESSED_XZ)) + strv[n++] = "xz-compressed"; + if (!compatible && (flags & HEADER_INCOMPATIBLE_COMPRESSED_LZ4)) + strv[n++] = "lz4-compressed"; + strv[n] = NULL; + assert(n < ELEMENTSOF(strv)); + + t = strv_join((char**) strv, ", "); + log_debug("Journal file %s uses %s %s %s disabled at compilation time.", + f->path, type, n > 1 ? "flags" : "flag", strnull(t)); + } + return true; + } + + return false; +} + +static int journal_file_verify_header(JournalFile *f) { assert(f); assert(f->header); if (memcmp(f->header->signature, HEADER_SIGNATURE, 8)) return -EBADMSG; - /* In both read and write mode we refuse to open files with - * incompatible flags we don't know */ - flags = le32toh(f->header->incompatible_flags); - if (flags & ~HEADER_INCOMPATIBLE_SUPPORTED) { - if (flags & ~HEADER_INCOMPATIBLE_ANY) - log_debug("Journal file %s has unknown incompatible flags %"PRIx32, - f->path, flags & ~HEADER_INCOMPATIBLE_ANY); - flags = (flags & HEADER_INCOMPATIBLE_ANY) & ~HEADER_INCOMPATIBLE_SUPPORTED; - if (flags) - log_debug("Journal file %s uses incompatible flags %"PRIx32 - " disabled at compilation time.", f->path, flags); + /* In both read and write mode we refuse to open files with incompatible + * flags we don't know. */ + if (warn_wrong_flags(f, false)) return -EPROTONOSUPPORT; - } - /* When open for writing we refuse to open files with - * compatible flags, too */ - flags = le32toh(f->header->compatible_flags); - if (f->writable && (flags & ~HEADER_COMPATIBLE_SUPPORTED)) { - if (flags & ~HEADER_COMPATIBLE_ANY) - log_debug("Journal file %s has unknown compatible flags %"PRIx32, - f->path, flags & ~HEADER_COMPATIBLE_ANY); - flags = (flags & HEADER_COMPATIBLE_ANY) & ~HEADER_COMPATIBLE_SUPPORTED; - if (flags) - log_debug("Journal file %s uses compatible flags %"PRIx32 - " disabled at compilation time.", f->path, flags); + /* When open for writing we refuse to open files with compatible flags, too. */ + if (f->writable && warn_wrong_flags(f, true)) return -EPROTONOSUPPORT; - } if (f->header->state >= _STATE_MAX) return -EBADMSG; @@ -3087,13 +3104,18 @@ int journal_file_open( } } - if (fname) + if (fname) { f->path = strdup(fname); - else /* If we don't know the path, fill in something explanatory and vaguely useful */ - asprintf(&f->path, "/proc/self/%i", fd); - if (!f->path) { - r = -ENOMEM; - goto fail; + if (!f->path) { + r = -ENOMEM; + goto fail; + } + } else { + /* If we don't know the path, fill in something explanatory and vaguely useful */ + if (asprintf(&f->path, "/proc/self/%i", fd) < 0) { + r = -ENOMEM; + goto fail; + } } f->chain_cache = ordered_hashmap_new(&uint64_hash_ops); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 2a5f2b37e8..2639fd6cf5 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1910,7 +1910,9 @@ static int access_check(sd_journal *j) { break; case EPROTONOSUPPORT: - log_warning_errno(err, "Journal file %s uses an unsupported feature, ignoring file.", path); + log_warning_errno(err, "Journal file %1$s uses an unsupported feature, ignoring file.\n" + "Use SYSTEMD_LOG_LEVEL=debug journalctl --file=%1$s to see the details.", + path); break; case EBADMSG: diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 4c618ed19e..1aac7ae979 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -240,7 +240,6 @@ static int list_seats(int argc, char *argv[], void *userdata) { sd_bus *bus = userdata; unsigned k = 0; int r; - assert(bus); assert(argv); @@ -280,35 +279,17 @@ static int list_seats(int argc, char *argv[], void *userdata) { } static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) { + _cleanup_free_ char *cgroup = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_free_ char *path = NULL; - const char *cgroup; unsigned c; int r; assert(bus); assert(unit); - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = sd_bus_get_property( - bus, - "org.freedesktop.systemd1", - path, - interface, - "ControlGroup", - &error, - &reply, - "s"); - if (r < 0) - return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "s", &cgroup); + r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup); if (r < 0) - return bus_log_parse_error(r); + return r; if (isempty(cgroup)) return 0; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 3873bf3e96..ad44ca290e 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2396,13 +2396,9 @@ static int method_set_wall_message( if (r == 0) return 1; /* Will call us back */ - if (isempty(wall_message)) - m->wall_message = mfree(m->wall_message); - else { - r = free_and_strdup(&m->wall_message, wall_message); - if (r < 0) - return log_oom(); - } + r = free_and_strdup(&m->wall_message, empty_to_null(wall_message)); + if (r < 0) + return log_oom(); m->enable_wall_messages = enable_wall_messages; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 31a40d47c3..4f5f659c7c 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -477,35 +477,17 @@ static int list_images(int argc, char *argv[], void *userdata) { } static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) { + _cleanup_free_ char *cgroup = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_free_ char *path = NULL; - const char *cgroup; int r; unsigned c; assert(bus); assert(unit); - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = sd_bus_get_property( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - &reply, - "s"); - if (r < 0) - return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "s", &cgroup); + r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup); if (r < 0) - return bus_log_parse_error(r); + return r; if (isempty(cgroup)) return 0; diff --git a/src/nspawn/nspawn-patch-uid.c b/src/nspawn/nspawn-patch-uid.c index ded5866d05..1a3f129db0 100644 --- a/src/nspawn/nspawn-patch-uid.c +++ b/src/nspawn/nspawn-patch-uid.c @@ -375,7 +375,7 @@ static int recurse_fd(int fd, bool donate_fd, const struct stat *st, uid_t shift FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) { struct stat fst; - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; if (fstatat(dirfd(d), de->d_name, &fst, AT_SYMLINK_NOFOLLOW) < 0) { diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 0954641c20..667774b906 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -1349,7 +1349,7 @@ void manager_cleanup_saved_user(Manager *m) { if (!IN_SET(de->d_type, DT_UNKNOWN, DT_REG)) continue; - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; r = parse_ifindex(de->d_name, &ifindex); diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index 5d21742a09..8765cf2f49 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -24,10 +24,15 @@ #include <stdlib.h> #include <string.h> +#include <systemd/sd-bus.h> + #include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" #include "fd-util.h" +#include "fileio.h" #include "format-util.h" #include "locale-util.h" #include "macro.h" @@ -36,6 +41,7 @@ #include "process-util.h" #include "string-util.h" #include "terminal-util.h" +#include "unit-name.h" static void show_pid_array( pid_t pids[], @@ -73,7 +79,7 @@ static void show_pid_array( for (i = 0; i < n_pids; i++) { _cleanup_free_ char *t = NULL; - get_process_cmdline(pids[i], n_columns, true, &t); + (void) get_process_cmdline(pids[i], n_columns, true, &t); if (extra) printf("%s%s ", prefix, special_glyph(TRIANGULAR_BULLET)); @@ -310,3 +316,81 @@ int show_cgroup_and_extra_by_spec( return show_cgroup_and_extra(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags); } + +int show_cgroup_get_unit_path_and_warn( + sd_bus *bus, + const char *unit, + char **ret) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + int r; + + path = unit_dbus_path_from_name(unit); + if (!path) + return log_oom(); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + unit_dbus_interface_from_name(unit), + "ControlGroup", + &error, + ret); + if (r < 0) + return log_error_errno(r, "Failed to query unit control group path: %s", + bus_error_message(&error, r)); + + return 0; +} + +int show_cgroup_get_path_and_warn( + const char *machine, + const char *prefix, + char **ret) { + + int r; + _cleanup_free_ char *root = NULL; + + if (machine) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *unit = NULL; + const char *m; + + m = strjoina("/run/systemd/machines/", machine); + r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); + if (r < 0) + return log_error_errno(r, "Failed to load machine data: %m"); + + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = show_cgroup_get_unit_path_and_warn(bus, unit, &root); + if (r < 0) + return r; + } else { + r = cg_get_root_path(&root); + if (r == -ENOMEDIUM) + return log_error_errno(r, "Failed to get root control group path.\n" + "No cgroup filesystem mounted on /sys/fs/cgroup"); + else if (r < 0) + return log_error_errno(r, "Failed to get root control group path: %m"); + } + + if (prefix) { + char *t; + + t = strjoin(root, prefix); + if (!t) + return log_oom(); + + *ret = t; + } else { + *ret = root; + root = NULL; + } + + return 0; +} diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h index 5c1d6e6d98..736f0f34c8 100644 --- a/src/shared/cgroup-show.h +++ b/src/shared/cgroup-show.h @@ -22,6 +22,8 @@ #include <stdbool.h> #include <sys/types.h> +#include <systemd/sd-bus.h> + #include "logs-show.h" #include "output-mode.h" @@ -30,3 +32,12 @@ int show_cgroup(const char *controller, const char *path, const char *prefix, un int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); + +int show_cgroup_get_unit_path_and_warn( + sd_bus *bus, + const char *unit, + char **ret); +int show_cgroup_get_path_and_warn( + const char *machine, + const char *prefix, + char **ret); diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c index f2d1555c13..f59f6f23ae 100644 --- a/src/shared/clean-ipc.c +++ b/src/shared/clean-ipc.c @@ -225,7 +225,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid) { FOREACH_DIRENT_ALL(de, dir, goto fail) { struct stat st; - if (STR_IN_SET(de->d_name, "..", ".")) + if (dot_or_dot_dot(de->d_name)) continue; if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { @@ -310,7 +310,7 @@ static int clean_posix_mq(uid_t uid, gid_t gid) { struct stat st; char fn[1+strlen(de->d_name)+1]; - if (STR_IN_SET(de->d_name, "..", ".")) + if (dot_or_dot_dot(de->d_name)) continue; if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c index 6ffb169b21..f1514c9638 100644 --- a/src/system-update-generator/system-update-generator.c +++ b/src/system-update-generator/system-update-generator.c @@ -22,6 +22,7 @@ #include "fs-util.h" #include "log.h" +#include "proc-cmdline.h" #include "special.h" #include "string-util.h" #include "util.h" @@ -47,11 +48,27 @@ static int generate_symlink(void) { if (symlink(SYSTEM_DATA_UNIT_PATH "/system-update.target", p) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", p); + return 1; +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + assert(key); + + /* Check if a run level is specified on the kernel command line. The + * command line has higher priority than any on-disk configuration, so + * it'll make any symlink we create moot. + */ + + if (streq(key, "systemd.unit") && !proc_cmdline_value_missing(key, value)) + log_warning("Offline system update overriden by kernel command line systemd.unit= setting"); + else if (!value && runlevel_to_target(key)) + log_warning("Offline system update overriden by runlevel \"%s\" on the kernel command line", key); + return 0; } int main(int argc, char *argv[]) { - int r; + int r, k; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); @@ -69,5 +86,11 @@ int main(int argc, char *argv[]) { r = generate_symlink(); + if (r > 0) { + k = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); + if (k < 0) + log_warning_errno(k, "Failed to parse kernel command line, ignoring: %m"); + } + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index a20ca1bcb5..8f80559baf 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -6937,6 +6937,7 @@ static void systemctl_help(void) { " -a --all Show all properties/all units currently in memory,\n" " including dead/empty ones. To list all units installed on\n" " the system, use the 'list-unit-files' command instead.\n" + " --failed Same as --state=failed\n" " -l --full Don't ellipsize unit names on output\n" " -r --recursive Show unit list of host and local containers\n" " --reverse Show reverse dependencies with 'list-dependencies'\n" diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 4cb465d0d2..e774f567e0 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -305,12 +305,23 @@ static void test_var_tmp(void) { } } +static void test_dot_or_dot_dot(void) { + assert_se(!dot_or_dot_dot(NULL)); + assert_se(!dot_or_dot_dot("")); + assert_se(!dot_or_dot_dot("xxx")); + assert_se(dot_or_dot_dot(".")); + assert_se(dot_or_dot_dot("..")); + assert_se(!dot_or_dot_dot(".foo")); + assert_se(!dot_or_dot_dot("..foo")); +} + int main(int argc, char *argv[]) { test_unlink_noerrno(); test_readlink_and_make_absolute(); test_get_files_in_directory(); test_var_tmp(); test_chase_symlinks(); + test_dot_or_dot_dot(); return 0; } diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index f4ce9791fb..c4f4d46ca1 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -385,7 +385,7 @@ static int dir_cleanup( usec_t age; _cleanup_free_ char *sub_path = NULL; - if (STR_IN_SET(dent->d_name, ".", "..")) + if (dot_or_dot_dot(dent->d_name)) continue; if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) { @@ -1070,9 +1070,7 @@ static int item_do_children(Item *i, const char *path, action_t action) { _cleanup_free_ char *p = NULL; int q; - errno = 0; - - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; p = strjoin(path, "/", de->d_name); |