diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 20bbae44871..2db2c2e1aa6 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -3333,7 +3333,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly b MountAPIVFS = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b BindJournalSockets = ...; + readonly b BindLogSockets = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s KeyringMode = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -3934,7 +3934,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - + @@ -4646,7 +4646,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - + @@ -5474,7 +5474,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly b MountAPIVFS = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b BindJournalSockets = ...; + readonly b BindLogSockets = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s KeyringMode = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -6087,7 +6087,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - + @@ -6773,7 +6773,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - + @@ -7465,7 +7465,7 @@ node /org/freedesktop/systemd1/unit/home_2emount { @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly b MountAPIVFS = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b BindJournalSockets = ...; + readonly b BindLogSockets = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s KeyringMode = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -8004,7 +8004,7 @@ node /org/freedesktop/systemd1/unit/home_2emount { - + @@ -8602,7 +8602,7 @@ node /org/freedesktop/systemd1/unit/home_2emount { - + @@ -9417,7 +9417,7 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly b MountAPIVFS = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b BindJournalSockets = ...; + readonly b BindLogSockets = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s KeyringMode = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -9942,7 +9942,7 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - + @@ -10526,7 +10526,7 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - + @@ -12175,7 +12175,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ LiveMountResult, PrivateTmpEx, ImportCredentialEx, and - BindJournalSockets were added in version 257. + BindLogSockets were added in version 257. Socket Unit Objects @@ -12214,7 +12214,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ PassFileDescriptorsToExec were added in version 256. PrivateTmpEx, ImportCredentialEx, and - BindJournalSockets were added in version 257. + BindLogSockets were added in version 257. Mount Unit Objects @@ -12250,7 +12250,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ MemoryZSwapWriteback were added in version 256. PrivateTmpEx, ImportCredentialEx, and - BindJournalSockets were added in version 257. + BindLogSockets were added in version 257. Swap Unit Objects @@ -12286,7 +12286,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ MemoryZSwapWriteback were added in version 256. PrivateTmpEx, ImportCredentialEx, and - BindJournalSockets were added in version 257. + BindLogSockets were added in version 257. Slice Unit Objects diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 03189615692..232ae7e96ec 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -367,7 +367,7 @@ - BindJournalSockets= + BindLogSockets= Takes a boolean argument. If true, sockets from systemd-journald.socket8 diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 4679f54a3e6..6023436b90a 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -55,7 +55,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system, protect_system, static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality, personality, unsigned long); static BUS_DEFINE_PROPERTY_GET(property_get_ioprio, "i", ExecContext, exec_context_get_effective_ioprio); static BUS_DEFINE_PROPERTY_GET(property_get_mount_apivfs, "b", ExecContext, exec_context_get_effective_mount_apivfs); -static BUS_DEFINE_PROPERTY_GET(property_get_bind_journal_sockets, "b", ExecContext, exec_context_get_effective_bind_journal_sockets); +static BUS_DEFINE_PROPERTY_GET(property_get_bind_log_sockets, "b", ExecContext, exec_context_get_effective_bind_log_sockets); static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_class, "i", ExecContext, exec_context_get_effective_ioprio, ioprio_prio_class); static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext, exec_context_get_effective_ioprio, ioprio_prio_data); static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL); @@ -1194,7 +1194,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MountAPIVFS", "b", property_get_mount_apivfs, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("BindJournalSockets", "b", property_get_bind_journal_sockets, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("BindLogSockets", "b", property_get_bind_log_sockets, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectProc", "s", property_get_protect_proc, offsetof(ExecContext, protect_proc), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset, offsetof(ExecContext, proc_subset), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1866,8 +1866,8 @@ int bus_exec_context_set_transient_property( if (streq(name, "MountAPIVFS")) return bus_set_transient_tristate(u, name, &c->mount_apivfs, message, flags, error); - if (streq(name, "BindJournalSockets")) - return bus_set_transient_tristate(u, name, &c->bind_journal_sockets, message, flags, error); + if (streq(name, "BindLogSockets")) + return bus_set_transient_tristate(u, name, &c->bind_log_sockets, message, flags, error); if (streq(name, "PrivateNetwork")) return bus_set_transient_bool(u, name, &c->private_network, message, flags, error); diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 1a2595c8bf4..f1d25b31126 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -2641,23 +2641,9 @@ static int compile_bind_mounts( return -ENOMEM; FOREACH_ARRAY(item, context->bind_mounts, context->n_bind_mounts) { - _cleanup_free_ char *s = NULL, *d = NULL; - - s = strdup(item->source); - if (!s) - return -ENOMEM; - - d = strdup(item->destination); - if (!d) - return -ENOMEM; - - bind_mounts[h++] = (BindMount) { - .source = TAKE_PTR(s), - .destination = TAKE_PTR(d), - .read_only = item->read_only, - .recursive = item->recursive, - .ignore_enoent = item->ignore_enoent, - }; + r = bind_mount_add(&bind_mounts, &h, item); + if (r < 0) + return r; } for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { @@ -3235,7 +3221,7 @@ static int apply_mount_namespace( .private_tmp = needs_sandboxing ? context->private_tmp : false, .mount_apivfs = needs_sandboxing && exec_context_get_effective_mount_apivfs(context), - .bind_journal_sockets = needs_sandboxing && exec_context_get_effective_bind_journal_sockets(context), + .bind_log_sockets = needs_sandboxing && exec_context_get_effective_bind_log_sockets(context), /* If NNP is on, we can turn on MS_NOSUID, since it won't have any effect anymore. */ .mount_nosuid = needs_sandboxing && context->no_new_privileges && !mac_selinux_use(), @@ -3857,7 +3843,7 @@ static bool exec_context_need_unprivileged_private_users( context->ipc_namespace_path || context->private_mounts > 0 || context->mount_apivfs > 0 || - context->bind_journal_sockets > 0 || + context->bind_log_sockets > 0 || context->n_bind_mounts > 0 || context->n_temporary_filesystems > 0 || context->root_directory || diff --git a/src/core/execute-serialize.c b/src/core/execute-serialize.c index 32d6118ab70..9f287dc12b3 100644 --- a/src/core/execute-serialize.c +++ b/src/core/execute-serialize.c @@ -1854,7 +1854,7 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) { if (r < 0) return r; - r = serialize_item_tristate(f, "exec-context-bind-journal-sockets", c->bind_journal_sockets); + r = serialize_item_tristate(f, "exec-context-bind-log-sockets", c->bind_log_sockets); if (r < 0) return r; @@ -2730,8 +2730,8 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) { r = safe_atoi(val, &c->mount_apivfs); if (r < 0) return r; - } else if ((val = startswith(l, "exec-context-bind-journal-sockets="))) { - r = safe_atoi(val, &c->bind_journal_sockets); + } else if ((val = startswith(l, "exec-context-bind-log-sockets="))) { + r = safe_atoi(val, &c->bind_log_sockets); if (r < 0) return r; } else if ((val = startswith(l, "exec-context-memory-ksm="))) { diff --git a/src/core/execute.c b/src/core/execute.c index 7a365e23b91..fdbe1e3210e 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -284,7 +284,7 @@ bool exec_needs_mount_namespace( context->directories[EXEC_DIRECTORY_LOGS].n_items > 0)) return true; - if (exec_context_get_effective_bind_journal_sockets(context)) + if (exec_context_get_effective_bind_log_sockets(context)) return true; return false; @@ -539,7 +539,7 @@ void exec_context_init(ExecContext *c) { .tty_cols = UINT_MAX, .private_mounts = -1, .mount_apivfs = -1, - .bind_journal_sockets = -1, + .bind_log_sockets = -1, .memory_ksm = -1, .set_login_environment = -1, }; @@ -980,7 +980,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { "%sProtectHome: %s\n" "%sProtectSystem: %s\n" "%sMountAPIVFS: %s\n" - "%sBindJournalSockets: %s\n" + "%sBindLogSockets: %s\n" "%sIgnoreSIGPIPE: %s\n" "%sMemoryDenyWriteExecute: %s\n" "%sRestrictRealtime: %s\n" @@ -1006,7 +1006,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { prefix, protect_home_to_string(c->protect_home), prefix, protect_system_to_string(c->protect_system), prefix, yes_no(exec_context_get_effective_mount_apivfs(c)), - prefix, yes_no(exec_context_get_effective_bind_journal_sockets(c)), + prefix, yes_no(exec_context_get_effective_bind_log_sockets(c)), prefix, yes_no(c->ignore_sigpipe), prefix, yes_no(c->memory_deny_write_execute), prefix, yes_no(c->restrict_realtime), @@ -1489,16 +1489,16 @@ bool exec_context_get_effective_mount_apivfs(const ExecContext *c) { return false; } -bool exec_context_get_effective_bind_journal_sockets(const ExecContext *c) { +bool exec_context_get_effective_bind_log_sockets(const ExecContext *c) { assert(c); /* If log namespace is specified, "/run/systemd/journal.namespace/" would be bind mounted to - * "/run/systemd/journal/", which effectively means BindJournalSockets=yes */ + * "/run/systemd/journal/", which effectively means BindLogSockets=yes */ if (c->log_namespace) return true; - if (c->bind_journal_sockets >= 0) - return c->bind_journal_sockets > 0; + if (c->bind_log_sockets >= 0) + return c->bind_log_sockets > 0; if (exec_context_get_effective_mount_apivfs(c)) return true; diff --git a/src/core/execute.h b/src/core/execute.h index 5754273999b..f9c88e9a763 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -313,7 +313,7 @@ struct ExecContext { int private_mounts; int mount_apivfs; - int bind_journal_sockets; + int bind_log_sockets; int memory_ksm; PrivateTmp private_tmp; bool private_network; @@ -520,7 +520,7 @@ bool exec_context_maintains_privileges(const ExecContext *c); int exec_context_get_effective_ioprio(const ExecContext *c); bool exec_context_get_effective_mount_apivfs(const ExecContext *c); -bool exec_context_get_effective_bind_journal_sockets(const ExecContext *c); +bool exec_context_get_effective_bind_log_sockets(const ExecContext *c); void exec_context_free_log_extra_fields(ExecContext *c); diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in index 32ac87ce85f..b6a9c708e49 100644 --- a/src/core/load-fragment-gperf.gperf.in +++ b/src/core/load-fragment-gperf.gperf.in @@ -137,7 +137,7 @@ {{type}}.ProtectHome, config_parse_protect_home, 0, offsetof({{type}}, exec_context.protect_home) {{type}}.MountFlags, config_parse_exec_mount_propagation_flag, 0, offsetof({{type}}, exec_context.mount_propagation_flag) {{type}}.MountAPIVFS, config_parse_tristate, 0, offsetof({{type}}, exec_context.mount_apivfs) -{{type}}.BindJournalSockets, config_parse_tristate, 0, offsetof({{type}}, exec_context.bind_journal_sockets) +{{type}}.BindLogSockets, config_parse_tristate, 0, offsetof({{type}}, exec_context.bind_log_sockets) {{type}}.Personality, config_parse_personality, 0, offsetof({{type}}, exec_context.personality) {{type}}.RuntimeDirectoryPreserve, config_parse_exec_preserve_mode, 0, offsetof({{type}}, exec_context.runtime_directory_preserve_mode) {{type}}.RuntimeDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_RUNTIME].mode) diff --git a/src/core/namespace.c b/src/core/namespace.c index 323ff4c2794..ba5163cdb8c 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -120,10 +120,10 @@ typedef struct MountList { size_t n_mounts; } MountList; -static const BindMount bind_journal_sockets_table[] = { - { (char*) "/run/systemd/journal/socket", (char*) "/run/systemd/journal/socket", .read_only = true, .ignore_enoent = true }, - { (char*) "/run/systemd/journal/stdout", (char*) "/run/systemd/journal/stdout", .read_only = true, .ignore_enoent = true }, - { (char*) "/run/systemd/journal/dev-log", (char*) "/run/systemd/journal/dev-log", .read_only = true, .ignore_enoent = true }, +static const BindMount bind_log_sockets_table[] = { + { (char*) "/run/systemd/journal/socket", (char*) "/run/systemd/journal/socket", .read_only = true, .nosuid = true, .noexec = true, .nodev = true, .ignore_enoent = true }, + { (char*) "/run/systemd/journal/stdout", (char*) "/run/systemd/journal/stdout", .read_only = true, .nosuid = true, .noexec = true, .nodev = true, .ignore_enoent = true }, + { (char*) "/run/systemd/journal/dev-log", (char*) "/run/systemd/journal/dev-log", .read_only = true, .nosuid = true, .noexec = true, .nodev = true, .ignore_enoent = true }, }; /* If MountAPIVFS= is used, let's mount /sys, /proc, /dev and /run into the it, but only as a fallback if the user hasn't mounted @@ -447,6 +447,8 @@ static int append_bind_mounts(MountList *ml, const BindMount *binds, size_t n) { .mode = b->recursive ? MOUNT_BIND_RECURSIVE : MOUNT_BIND, .read_only = b->read_only, .nosuid = b->nosuid, + .noexec = b->noexec, + .flags = b->nodev ? MS_NODEV : 0, .source_const = b->source, .ignore = b->ignore_enoent, }; @@ -1146,7 +1148,9 @@ static int mount_private_dev(const MountEntry *m, const NamespaceParameters *p) FOREACH_STRING(d, "/dev/mqueue", "/dev/hugepages") (void) bind_mount_device_dir(temporary_mount, d); - if ((!p->root_image && !p->root_directory) || p->bind_journal_sockets) { + /* We assume /run/systemd/journal/ is available if not changing root, which isn't entirely accurate + * but shouldn't matter, as either way the user would get ENOENT when accessing /dev/log */ + if ((!p->root_image && !p->root_directory) || p->bind_log_sockets) { const char *devlog = strjoina(temporary_mount, "/dev/log"); if (symlink("/run/systemd/journal/dev-log", devlog) < 0) log_debug_errno(errno, @@ -2597,8 +2601,8 @@ int setup_namespace(const NamespaceParameters *p, char **error_path) { .source_malloc = TAKE_PTR(q), }; - } else if (p->bind_journal_sockets) { - r = append_bind_mounts(&ml, bind_journal_sockets_table, ELEMENTSOF(bind_journal_sockets_table)); + } else if (p->bind_log_sockets) { + r = append_bind_mounts(&ml, bind_log_sockets_table, ELEMENTSOF(bind_log_sockets_table)); if (r < 0) return r; } @@ -2777,7 +2781,6 @@ void bind_mount_free_many(BindMount *b, size_t n) { int bind_mount_add(BindMount **b, size_t *n, const BindMount *item) { _cleanup_free_ char *s = NULL, *d = NULL; - BindMount *c; assert(b); assert(n); @@ -2791,17 +2794,16 @@ int bind_mount_add(BindMount **b, size_t *n, const BindMount *item) { if (!d) return -ENOMEM; - c = reallocarray(*b, *n + 1, sizeof(BindMount)); - if (!c) + if (!GREEDY_REALLOC(*b, *n + 1)) return -ENOMEM; - *b = c; - - c[(*n)++] = (BindMount) { + (*b)[(*n)++] = (BindMount) { .source = TAKE_PTR(s), .destination = TAKE_PTR(d), .read_only = item->read_only, + .nodev = item->nodev, .nosuid = item->nosuid, + .noexec = item->noexec, .recursive = item->recursive, .ignore_enoent = item->ignore_enoent, }; diff --git a/src/core/namespace.h b/src/core/namespace.h index 538d23753c2..d961a66b4f3 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -65,7 +65,9 @@ struct BindMount { char *source; char *destination; bool read_only; + bool nodev; bool nosuid; + bool noexec; bool recursive; bool ignore_enoent; }; @@ -152,7 +154,7 @@ struct NamespaceParameters { bool private_ipc; bool mount_apivfs; - bool bind_journal_sockets; + bool bind_log_sockets; bool mount_nosuid; ProtectHome protect_home; diff --git a/src/core/service.c b/src/core/service.c index 663fdb30f2c..ca1f54340d0 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1130,42 +1130,37 @@ static int service_is_suitable_main_pid(Service *s, PidRef *pid, int prio) { static int service_load_pid_file(Service *s, bool may_warn) { _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; - bool questionable_pid_file = false; + _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *k = NULL; - _cleanup_close_ int fd = -EBADF; - int r, prio; + bool questionable_pid_file = false; + int r, prio = may_warn ? LOG_INFO : LOG_DEBUG; assert(s); if (!s->pid_file) return -ENOENT; - prio = may_warn ? LOG_INFO : LOG_DEBUG; - - r = chase(s->pid_file, NULL, CHASE_SAFE, NULL, &fd); + r = chase_and_fopen_unlocked(s->pid_file, NULL, CHASE_SAFE, "re", NULL, &f); if (r == -ENOLINK) { log_unit_debug_errno(UNIT(s), r, "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); questionable_pid_file = true; - r = chase(s->pid_file, NULL, 0, NULL, &fd); + r = chase_and_fopen_unlocked(s->pid_file, NULL, 0, "re", NULL, &f); } if (r < 0) return log_unit_full_errno(UNIT(s), prio, r, - "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); + "Can't open PID file '%s' (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); - /* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd - * chase() returned us into a proper fd first. */ - r = read_one_line_file(FORMAT_PROC_FD_PATH(fd), &k); + /* Let's read the PID file now that we chased it down. */ + r = read_line(f, LINE_MAX, &k); if (r < 0) - return log_unit_error_errno(UNIT(s), r, - "Can't convert PID files %s O_PATH file descriptor to proper file descriptor: %m", - s->pid_file); + return log_unit_error_errno(UNIT(s), r, "Failed to read PID file '%s': %m", s->pid_file); r = pidref_set_pidstr(&pidref, k); if (r < 0) - return log_unit_full_errno(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file); + return log_unit_full_errno(UNIT(s), prio, r, "Failed to create reference to PID %s from file '%s': %m", k, s->pid_file); if (s->main_pid_known && pidref_equal(&pidref, &s->main_pid)) return 0; @@ -1182,14 +1177,14 @@ static int service_load_pid_file(Service *s, bool may_warn) { /* Hmm, it's not clear if the new main PID is safe. Let's allow this if the PID file is owned by root */ - if (fstat(fd, &st) < 0) - return log_unit_error_errno(UNIT(s), errno, "Failed to fstat() PID file O_PATH fd: %m"); + if (fstat(fileno(f), &st) < 0) + return log_unit_error_errno(UNIT(s), errno, "Failed to fstat() PID file '%s': %m", s->pid_file); if (st.st_uid != 0) return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EPERM), - "New main PID "PID_FMT" does not belong to service, and PID file is not owned by root. Refusing.", pidref.pid); + "New main PID "PID_FMT" from PID file does not belong to service, and PID file is not owned by root. Refusing.", pidref.pid); - log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, but we'll accept it since PID file is owned by root.", pidref.pid); + log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, accepting anyway since PID file is owned by root.", pidref.pid); } if (s->main_pid_known) { @@ -1456,10 +1451,9 @@ static int service_collect_fds( rn_socket_fds = 1; } else { - Unit *u; - /* Pass all our configured sockets for singleton services */ + Unit *u; UNIT_FOREACH_DEPENDENCY(u, UNIT(s), UNIT_ATOM_TRIGGERED_BY) { _cleanup_free_ int *cfds = NULL; int cn_fds; @@ -1472,8 +1466,7 @@ static int service_collect_fds( cn_fds = socket_collect_fds(sock, &cfds); if (cn_fds < 0) return cn_fds; - - if (cn_fds <= 0) + if (cn_fds == 0) continue; if (!rfds) { @@ -2029,22 +2022,6 @@ static ServiceState service_determine_dead_state(Service *s) { return s->fd_store && s->fd_store_preserve_mode == EXEC_PRESERVE_YES ? SERVICE_DEAD_RESOURCES_PINNED : SERVICE_DEAD; } -static void service_set_debug_invocation(Service *s, bool enable) { - assert(s); - - if (s->restart_mode != SERVICE_RESTART_MODE_DEBUG) - return; - - if (enable == UNIT(s)->debug_invocation) - return; /* Nothing to do */ - - UNIT(s)->debug_invocation = enable; - unit_overwrite_log_level_max(UNIT(s), enable ? LOG_PRI(LOG_DEBUG) : s->exec_context.log_level_max); - - if (enable) - log_unit_notice(UNIT(s), "Service failed, subsequent restarts will be executed with debug level logging."); -} - static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) { ServiceState end_state, restart_state; int r; @@ -2108,13 +2085,19 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) return service_enter_dead(s, SERVICE_FAILURE_RESOURCES, /* allow_restart= */ false); } - log_unit_debug(UNIT(s), "Next restart interval calculated as: %s", FORMAT_TIMESPAN(restart_usec_next, 0)); - /* If the relevant option is set, and the unit doesn't already have logging level set to * debug, enable it now. Make sure to overwrite the state in /run/systemd/units/ too, to * ensure journald doesn't prune the messages. The previous state is saved and restored * once the auto-restart flow ends. */ - service_set_debug_invocation(s, /* enable= */ true); + if (s->restart_mode == SERVICE_RESTART_MODE_DEBUG) { + r = unit_set_debug_invocation(UNIT(s), true); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "Failed to enable debug invocation, ignoring: %m"); + if (r > 0) + log_unit_notice(UNIT(s), "Service dead, subsequent restarts will be executed with debug level logging."); + } + + log_unit_debug(UNIT(s), "Next restart interval calculated as: %s", FORMAT_TIMESPAN(restart_usec_next, 0)); service_set_state(s, SERVICE_AUTO_RESTART); } else { @@ -2123,7 +2106,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) * can still introspect the counter. */ service_set_state(s, end_state); - service_set_debug_invocation(s, /* enable= */ false); + (void) unit_set_debug_invocation(UNIT(s), false); } /* The new state is in effect, let's decrease the fd store ref counter again. Let's also re-add us to the GC @@ -4959,7 +4942,7 @@ static void service_reset_failed(Unit *u) { s->live_mount_result = SERVICE_SUCCESS; s->n_restarts = 0; - service_set_debug_invocation(s, /* enable= */ false); + (void) unit_set_debug_invocation(u, /* enable= */ false); } static PidRef* service_main_pid(Unit *u, bool *ret_is_alien) { diff --git a/src/core/unit-serialize.c b/src/core/unit-serialize.c index 8baa30f9e5f..f96bae19f9e 100644 --- a/src/core/unit-serialize.c +++ b/src/core/unit-serialize.c @@ -101,6 +101,8 @@ int unit_serialize_state(Unit *u, FILE *f, FDSet *fds, bool switching_root) { (void) serialize_bool(f, "transient", u->transient); (void) serialize_bool(f, "in-audit", u->in_audit); + (void) serialize_bool(f, "debug-invocation", u->debug_invocation); + (void) serialize_bool(f, "exported-invocation-id", u->exported_invocation_id); (void) serialize_bool(f, "exported-log-level-max", u->exported_log_level_max); (void) serialize_bool(f, "exported-log-extra-fields", u->exported_log_extra_fields); @@ -265,6 +267,9 @@ int unit_deserialize_state(Unit *u, FILE *f, FDSet *fds) { else if (MATCH_DESERIALIZE("in-audit", l, v, parse_boolean, u->in_audit)) continue; + else if (MATCH_DESERIALIZE("debug-invocation", l, v, parse_boolean, u->debug_invocation)) + continue; + else if (MATCH_DESERIALIZE("exported-invocation-id", l, v, parse_boolean, u->exported_invocation_id)) continue; diff --git a/src/core/unit.c b/src/core/unit.c index 4468733a636..cebae4d53e4 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -5839,14 +5839,27 @@ void unit_unlink_state_files(Unit *u) { } } -int unit_overwrite_log_level_max(Unit *u, int log_level_max) { +int unit_set_debug_invocation(Unit *u, bool enable) { + int r; + assert(u); - if (!u->exported_log_level_max) + if (u->debug_invocation == enable) return 0; /* Nothing to do */ + u->debug_invocation = enable; + /* Ensure that the new log level is exported for the journal, in place of the previous one */ - return unit_export_log_level_max(u, log_level_max, /* overwrite= */ true); + if (u->exported_log_level_max) { + const ExecContext *ec = unit_get_exec_context(u); + if (ec) { + r = unit_export_log_level_max(u, enable ? LOG_PRI(LOG_DEBUG) : ec->log_level_max, /* overwrite= */ true); + if (r < 0) + return r; + } + } + + return 1; } int unit_prepare_exec(Unit *u) { diff --git a/src/core/unit.h b/src/core/unit.h index 8aac5f59992..5ffd82b67eb 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -992,7 +992,8 @@ void unit_remove_dependencies(Unit *u, UnitDependencyMask mask); void unit_export_state_files(Unit *u); void unit_unlink_state_files(Unit *u); -int unit_overwrite_log_level_max(Unit *u, int log_level_max); + +int unit_set_debug_invocation(Unit *u, bool enable); int unit_prepare_exec(Unit *u); diff --git a/src/portable/profile/default/service.conf b/src/portable/profile/default/service.conf index 07f985cefa5..35dfd778f28 100644 --- a/src/portable/profile/default/service.conf +++ b/src/portable/profile/default/service.conf @@ -2,7 +2,7 @@ [Service] MountAPIVFS=yes -BindJournalSockets=yes +BindLogSockets=yes BindReadOnlyPaths=/etc/machine-id BindReadOnlyPaths=-/etc/resolv.conf BindReadOnlyPaths=/run/dbus/system_bus_socket diff --git a/src/portable/profile/nonetwork/service.conf b/src/portable/profile/nonetwork/service.conf index ee7aa2d5253..e8d2a9bb1a1 100644 --- a/src/portable/profile/nonetwork/service.conf +++ b/src/portable/profile/nonetwork/service.conf @@ -2,7 +2,7 @@ [Service] MountAPIVFS=yes -BindJournalSockets=yes +BindLogSockets=yes BindReadOnlyPaths=/etc/machine-id BindReadOnlyPaths=/run/dbus/system_bus_socket DynamicUser=yes diff --git a/src/portable/profile/strict/service.conf b/src/portable/profile/strict/service.conf index ed14387b5d0..aa5bcfbb08e 100644 --- a/src/portable/profile/strict/service.conf +++ b/src/portable/profile/strict/service.conf @@ -2,7 +2,7 @@ [Service] MountAPIVFS=yes -BindJournalSockets=yes +BindLogSockets=yes BindReadOnlyPaths=/etc/machine-id DynamicUser=yes RemoveIPC=yes diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index edfe1482c81..6987a885d1e 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -1076,7 +1076,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con "ProtectClock", "ProtectControlGroups", "MountAPIVFS", - "BindJournalSockets", + "BindLogSockets", "CPUSchedulingResetOnFork", "LockPersonality", "ProtectHostname", diff --git a/test/units/TEST-50-DISSECT.dissect.sh b/test/units/TEST-50-DISSECT.dissect.sh index 5e4899788f9..15f663faf54 100755 --- a/test/units/TEST-50-DISSECT.dissect.sh +++ b/test/units/TEST-50-DISSECT.dissect.sh @@ -74,9 +74,9 @@ fi systemd-dissect --umount "$IMAGE_DIR/mount" systemd-dissect --umount "$IMAGE_DIR/mount2" -# Test BindJournalSockets= +# Test BindLogSockets= systemd-run --wait -p RootImage="$MINIMAL_IMAGE.raw" mountpoint /run/systemd/journal/socket -(! systemd-run --wait -p RootImage="$MINIMAL_IMAGE.raw" -p BindJournalSockets=no ls /run/systemd/journal/socket) +(! systemd-run --wait -p RootImage="$MINIMAL_IMAGE.raw" -p BindLogSockets=no ls /run/systemd/journal/socket) (! systemd-run --wait -p RootImage="$MINIMAL_IMAGE.raw" -p MountAPIVFS=no ls /run/systemd/journal/socket) systemd-run -P -p RootImage="$MINIMAL_IMAGE.raw" cat /usr/lib/os-release | grep -q -F "MARKER=1" @@ -86,7 +86,7 @@ systemd-run -P \ -p RootImage="$MINIMAL_IMAGE.raw" \ -p RootHash="$MINIMAL_IMAGE.foohash" \ -p RootVerity="$MINIMAL_IMAGE.fooverity" \ - -p BindJournalSockets=yes \ + -p BindLogSockets=yes \ cat /usr/lib/os-release | grep -q -F "MARKER=1" # Let's use the long option name just here as a test systemd-run -P \