From 986935cf6adccf47f5a8a543885fb1d36f5dfb61 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Wed, 22 Apr 2020 16:16:47 +0200 Subject: [PATCH 1/6] pid1: update manager settings on reload too Most complexity of this patch is due to the fact that some manager settings (basically the watchdog properties) can be set at runtime and in this case the runtime values must be retained over daemon-reload or daemon-reexec. For consistency sake, all watchdog properties behaves now the same way, that is: - Values defined by config files can be overridden by writing the new value through their respective D-BUS properties. In this case, these values are preserved over reload/reexec until the special value '0' or USEC_INFINITY is written, which will then restore the last values loaded from the config files. If the restored value is '0' or 'USEC_INFINITY', the watchdogs will be disabled and the corresponding device will be closed. - Reading the properties from a user instance will return the USEC_INFINITY value as these properties are only meaningful for PID1. - Writing to one of the watchdog properties of a user instance's will be a NOP. Fixes: #15453 --- src/core/dbus-manager.c | 114 +++++++++++++++++++++++++++++++++++----- src/core/main.c | 28 +++++----- src/core/manager.c | 101 +++++++++++++++++++++++++++++++++-- src/core/manager.h | 16 ++++-- 4 files changed, 226 insertions(+), 33 deletions(-) diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index f8a13bd637..51254b92da 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -244,6 +244,76 @@ static int property_get_show_status( return sd_bus_message_append_basic(reply, 'b', &b); } +static int property_get_runtime_watchdog( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(m); + assert(bus); + assert(reply); + + return sd_bus_message_append(reply, "t", manager_get_watchdog(m, WATCHDOG_RUNTIME)); +} + +static int property_get_reboot_watchdog( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(m); + assert(bus); + assert(reply); + + return sd_bus_message_append(reply, "t", manager_get_watchdog(m, WATCHDOG_REBOOT)); +} + +static int property_get_kexec_watchdog( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(m); + assert(bus); + assert(reply); + + return sd_bus_message_append(reply, "t", manager_get_watchdog(m, WATCHDOG_KEXEC)); +} + +static int property_set_watchdog(Manager *m, WatchdogType type, sd_bus_message *value) { + usec_t timeout; + int r; + + assert(m); + assert(value); + + assert_cc(sizeof(usec_t) == sizeof(uint64_t)); + + r = sd_bus_message_read(value, "t", &timeout); + if (r < 0) + return r; + + return manager_set_watchdog_overridden(m, type, timeout); +} + static int property_set_runtime_watchdog( sd_bus *bus, const char *path, @@ -253,19 +323,37 @@ static int property_set_runtime_watchdog( void *userdata, sd_bus_error *error) { - usec_t *t = userdata; - int r; + return property_set_watchdog(userdata, WATCHDOG_RUNTIME, value); +} +static int property_set_reboot_watchdog( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *value, + void *userdata, + sd_bus_error *error) { + + return property_set_watchdog(userdata, WATCHDOG_REBOOT, value); +} + +static int property_set_kexec_watchdog( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *value, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(m); assert(bus); assert(value); - assert_cc(sizeof(usec_t) == sizeof(uint64_t)); - - r = sd_bus_message_read(value, "t", t); - if (r < 0) - return r; - - return watchdog_set_timeout(t); + return property_set_watchdog(userdata, WATCHDOG_KEXEC, value); } static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) { @@ -2404,11 +2492,11 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.search_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0), - SD_BUS_WRITABLE_PROPERTY("RebootWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), 0), + SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", property_get_runtime_watchdog, property_set_runtime_watchdog, 0, 0), + SD_BUS_WRITABLE_PROPERTY("RebootWatchdogUSec", "t", property_get_reboot_watchdog, property_set_reboot_watchdog, 0, 0), /* The following item is an obsolete alias */ - SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), SD_BUS_VTABLE_HIDDEN), - SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, kexec_watchdog), 0), + SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", property_get_reboot_watchdog, property_set_reboot_watchdog, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", property_get_kexec_watchdog, property_set_kexec_watchdog, 0, 0), SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0), SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0), SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0), diff --git a/src/core/main.c b/src/core/main.c index c9eaf70bd6..4cb61af745 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -703,16 +703,18 @@ static void set_manager_settings(Manager *m) { assert(m); - /* Propagates the various manager settings into the manager object, i.e. properties that effect the manager - * itself (as opposed to just being inherited into newly allocated units, see set_manager_defaults() above). */ + /* Propagates the various manager settings into the manager object, i.e. properties that + * effect the manager itself (as opposed to just being inherited into newly allocated + * units, see set_manager_defaults() above). */ m->confirm_spawn = arg_confirm_spawn; m->service_watchdogs = arg_service_watchdogs; - m->runtime_watchdog = arg_runtime_watchdog; - m->reboot_watchdog = arg_reboot_watchdog; - m->kexec_watchdog = arg_kexec_watchdog; m->cad_burst_action = arg_cad_burst_action; + manager_set_watchdog(m, WATCHDOG_RUNTIME, arg_runtime_watchdog); + manager_set_watchdog(m, WATCHDOG_REBOOT, arg_reboot_watchdog); + manager_set_watchdog(m, WATCHDOG_KEXEC, arg_kexec_watchdog); + manager_set_show_status(m, arg_show_status, "commandline"); m->status_unit_format = arg_status_unit_format; } @@ -1784,6 +1786,7 @@ static int invoke_main_loop( (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock); set_manager_defaults(m); + set_manager_settings(m); update_cpu_affinity(false); update_numa_policy(false); @@ -1974,9 +1977,6 @@ static int initialize_runtime( if (r < 0) log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m", arg_watchdog_device); } - - if (timestamp_is_set(arg_runtime_watchdog)) - watchdog_set_timeout(&arg_runtime_watchdog); } if (arg_timer_slack_nsec != NSEC_INFINITY) @@ -2250,6 +2250,10 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile, /* Note that this also parses bits from the kernel command line, including "debug". */ log_parse_environment(); + /* Initialize the show status setting if it hasn't been set explicitly yet */ + if (arg_show_status == _SHOW_STATUS_INVALID) + arg_show_status = SHOW_STATUS_YES; + return 0; } @@ -2273,10 +2277,6 @@ static int load_configuration( return r; } - /* Initialize the show status setting if it hasn't been set explicitly yet */ - if (arg_show_status == _SHOW_STATUS_INVALID) - arg_show_status = SHOW_STATUS_YES; - return 0; } @@ -2753,8 +2753,8 @@ finish: pager_close(); if (m) { - arg_reboot_watchdog = m->reboot_watchdog; - arg_kexec_watchdog = m->kexec_watchdog; + arg_reboot_watchdog = manager_get_watchdog(m, WATCHDOG_REBOOT); + arg_kexec_watchdog = manager_get_watchdog(m, WATCHDOG_KEXEC); m = manager_free(m); } diff --git a/src/core/manager.c b/src/core/manager.c index 1beab6baed..c57ad1490d 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -779,6 +779,10 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager .original_log_level = -1, .original_log_target = _LOG_TARGET_INVALID, + .watchdog_overridden[WATCHDOG_RUNTIME] = USEC_INFINITY, + .watchdog_overridden[WATCHDOG_REBOOT] = USEC_INFINITY, + .watchdog_overridden[WATCHDOG_KEXEC] = USEC_INFINITY, + .notify_fd = -1, .cgroups_agent_fd = -1, .signal_fd = -1, @@ -2922,9 +2926,10 @@ int manager_loop(Manager *m) { return log_error_errno(r, "Failed to enable SIGCHLD event source: %m"); while (m->objective == MANAGER_OK) { - usec_t wait_usec; + usec_t wait_usec, watchdog_usec; - if (timestamp_is_set(m->runtime_watchdog) && MANAGER_IS_SYSTEM(m)) + watchdog_usec = manager_get_watchdog(m, WATCHDOG_RUNTIME); + if (timestamp_is_set(watchdog_usec)) watchdog_ping(); if (!ratelimit_below(&rl)) { @@ -2955,7 +2960,7 @@ int manager_loop(Manager *m) { continue; /* Sleep for watchdog runtime wait time */ - if (MANAGER_IS_SYSTEM(m)) + if (timestamp_is_set(watchdog_usec)) wait_usec = watchdog_runtime_wait(); else wait_usec = USEC_INFINITY; @@ -3196,6 +3201,10 @@ int manager_serialize( if (m->log_target_overridden) (void) serialize_item(f, "log-target-override", log_target_to_string(log_get_target())); + (void) serialize_usec(f, "runtime-watchdog-overridden", m->watchdog_overridden[WATCHDOG_RUNTIME]); + (void) serialize_usec(f, "reboot-watchdog-overridden", m->watchdog_overridden[WATCHDOG_REBOOT]); + (void) serialize_usec(f, "kexec-watchdog-overridden", m->watchdog_overridden[WATCHDOG_KEXEC]); + for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { _cleanup_free_ char *joined = NULL; @@ -3328,6 +3337,68 @@ static int manager_deserialize_units(Manager *m, FILE *f, FDSet *fds) { return 0; } +usec_t manager_get_watchdog(Manager *m, WatchdogType t) { + assert(m); + + if (MANAGER_IS_USER(m)) + return USEC_INFINITY; + + if (timestamp_is_set(m->watchdog_overridden[t])) + return m->watchdog_overridden[t]; + + return m->watchdog[t]; +} + +void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout) { + int r = 0; + + assert(m); + + if (MANAGER_IS_USER(m)) + return; + + if (m->watchdog[t] == timeout) + return; + + if (t == WATCHDOG_RUNTIME) + if (!timestamp_is_set(m->watchdog_overridden[WATCHDOG_RUNTIME])) { + if (timestamp_is_set(timeout)) + r = watchdog_set_timeout(&timeout); + else + watchdog_close(true); + } + + if (r >= 0) + m->watchdog[t] = timeout; +} + +int manager_set_watchdog_overridden(Manager *m, WatchdogType t, usec_t timeout) { + int r = 0; + + assert(m); + + if (MANAGER_IS_USER(m)) + return 0; + + if (m->watchdog_overridden[t] == timeout) + return 0; + + if (t == WATCHDOG_RUNTIME) { + usec_t *p; + + p = timestamp_is_set(timeout) ? &timeout : &m->watchdog[t]; + if (timestamp_is_set(*p)) + r = watchdog_set_timeout(p); + else + watchdog_close(true); + } + + if (r >= 0) + m->watchdog_overridden[t] = timeout; + + return 0; +} + int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { int r = 0; @@ -3451,6 +3522,30 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { else manager_override_log_target(m, target); + } else if ((val = startswith(l, "runtime-watchdog-overridden="))) { + usec_t t; + + if (deserialize_usec(val, &t) < 0) + log_notice("Failed to parse runtime-watchdog-overridden value '%s', ignoring.", val); + else + manager_set_watchdog_overridden(m, WATCHDOG_RUNTIME, t); + + } else if ((val = startswith(l, "reboot-watchdog-overridden="))) { + usec_t t; + + if (deserialize_usec(val, &t) < 0) + log_notice("Failed to parse reboot-watchdog-overridden value '%s', ignoring.", val); + else + manager_set_watchdog_overridden(m, WATCHDOG_REBOOT, t); + + } else if ((val = startswith(l, "kexec-watchdog-overridden="))) { + usec_t t; + + if (deserialize_usec(val, &t) < 0) + log_notice("Failed to parse kexec-watchdog-overridden value '%s', ignoring.", val); + else + manager_set_watchdog_overridden(m, WATCHDOG_KEXEC, t); + } else if (startswith(l, "env=")) { r = deserialize_environment(l + 4, &m->client_environment); if (r < 0) diff --git a/src/core/manager.h b/src/core/manager.h index 10c34f9543..89ae3d09fd 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -114,6 +114,13 @@ typedef enum ManagerTimestamp { _MANAGER_TIMESTAMP_INVALID = -1, } ManagerTimestamp; +typedef enum WatchdogType { + WATCHDOG_RUNTIME, + WATCHDOG_REBOOT, + WATCHDOG_KEXEC, + _WATCHDOG_TYPE_MAX, +} WatchdogType; + #include "execute.h" #include "job.h" #include "path-lookup.h" @@ -231,9 +238,8 @@ struct Manager { char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */ char **client_environment; /* Environment variables created by clients through the bus API */ - usec_t runtime_watchdog; - usec_t reboot_watchdog; - usec_t kexec_watchdog; + usec_t watchdog[_WATCHDOG_TYPE_MAX]; + usec_t watchdog_overridden[_WATCHDOG_TYPE_MAX]; dual_timestamp timestamps[_MANAGER_TIMESTAMP_MAX]; @@ -555,5 +561,9 @@ const char *manager_timestamp_to_string(ManagerTimestamp m) _const_; ManagerTimestamp manager_timestamp_from_string(const char *s) _pure_; ManagerTimestamp manager_timestamp_initrd_mangle(ManagerTimestamp s); +usec_t manager_get_watchdog(Manager *m, WatchdogType t); +void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout); +int manager_set_watchdog_overridden(Manager *m, WatchdogType t, usec_t timeout); + const char* oom_policy_to_string(OOMPolicy i) _const_; OOMPolicy oom_policy_from_string(const char *s) _pure_; From ffe5c01eaaf4fd7acda2553e76ab42518c215312 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Mon, 27 Apr 2020 08:36:47 +0200 Subject: [PATCH 2/6] pid1: fold load_configuration() into main() That's reduce the number of functions dealing with configuration parsing/loading and should make the code simpler especially since this function was used only once. No functional change. --- src/core/main.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 4cb61af745..b60bbaf61f 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2257,29 +2257,6 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile, return 0; } -static int load_configuration( - int argc, - char **argv, - const struct rlimit *saved_rlimit_nofile, - const struct rlimit *saved_rlimit_memlock, - const char **ret_error_message) { - int r; - - assert(saved_rlimit_nofile); - assert(saved_rlimit_memlock); - assert(ret_error_message); - - (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock); - - r = parse_argv(argc, argv); - if (r < 0) { - *ret_error_message = "Failed to parse commandline arguments"; - return r; - } - - return 0; -} - static int safety_checks(void) { if (getpid_cached() == 1 && @@ -2618,9 +2595,13 @@ int main(int argc, char *argv[]) { (void) reset_all_signal_handlers(); (void) ignore_signals(SIGNALS_IGNORE, -1); - r = load_configuration(argc, argv, &saved_rlimit_nofile, &saved_rlimit_memlock, &error_message); - if (r < 0) + (void) parse_configuration(&saved_rlimit_nofile, &saved_rlimit_memlock); + + r = parse_argv(argc, argv); + if (r < 0) { + error_message = "Failed to parse commandline arguments"; goto finish; + } r = safety_checks(); if (r < 0) From 1addc46c8ce50e4bb4f20f3e010e5c190b352cd7 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Mon, 27 Apr 2020 08:49:53 +0200 Subject: [PATCH 3/6] pid1: make manager_flip_auto_status() static No functional change. --- src/core/manager.c | 2 +- src/core/manager.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index c57ad1490d..842b51c5d3 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -181,7 +181,7 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po } } -void manager_flip_auto_status(Manager *m, bool enable, const char *reason) { +static void manager_flip_auto_status(Manager *m, bool enable, const char *reason) { assert(m); if (enable) { diff --git a/src/core/manager.h b/src/core/manager.h index 89ae3d09fd..34714eb09e 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -516,7 +516,6 @@ void manager_set_show_status(Manager *m, ShowStatus mode, const char *reason); void manager_set_first_boot(Manager *m, bool b); void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) _printf_(4,5); -void manager_flip_auto_status(Manager *m, bool enable, const char *reason); Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path); From 06a4eb0737fe4793cf863447c199b2acfc77ab81 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Mon, 27 Apr 2020 08:54:44 +0200 Subject: [PATCH 4/6] pid1: make manager_vacuum_{uid,gid}_refs() static No functional change. --- src/core/manager.c | 33 +++++++++++++++++---------------- src/core/manager.h | 3 --- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 842b51c5d3..b9aeb0e515 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -110,6 +110,7 @@ static int manager_dispatch_sigchld(sd_event_source *source, void *userdata); static int manager_dispatch_timezone_change(sd_event_source *source, const struct inotify_event *event, void *userdata); static int manager_run_environment_generators(Manager *m); static int manager_run_generators(Manager *m); +static void manager_vacuum(Manager *m); static usec_t manager_watch_jobs_next_time(Manager *m) { return usec_add(now(CLOCK_MONOTONIC), @@ -1600,20 +1601,6 @@ static void manager_preset_all(Manager *m) { log_info("Populated /etc with preset unit settings."); } -static void manager_vacuum(Manager *m) { - assert(m); - - /* Release any dynamic users no longer referenced */ - dynamic_user_vacuum(m, true); - - /* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */ - manager_vacuum_uid_refs(m); - manager_vacuum_gid_refs(m); - - /* Release any runtimes no longer referenced */ - exec_runtime_vacuum(m); -} - static void manager_ready(Manager *m) { assert(m); @@ -4536,14 +4523,28 @@ static void manager_vacuum_uid_refs_internal( } } -void manager_vacuum_uid_refs(Manager *m) { +static void manager_vacuum_uid_refs(Manager *m) { manager_vacuum_uid_refs_internal(m, &m->uid_refs, clean_ipc_by_uid); } -void manager_vacuum_gid_refs(Manager *m) { +static void manager_vacuum_gid_refs(Manager *m) { manager_vacuum_uid_refs_internal(m, &m->gid_refs, clean_ipc_by_gid); } +static void manager_vacuum(Manager *m) { + assert(m); + + /* Release any dynamic users no longer referenced */ + dynamic_user_vacuum(m, true); + + /* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */ + manager_vacuum_uid_refs(m); + manager_vacuum_gid_refs(m); + + /* Release any runtimes no longer referenced */ + exec_runtime_vacuum(m); +} + static void manager_serialize_uid_refs_internal( Manager *m, FILE *f, diff --git a/src/core/manager.h b/src/core/manager.h index 34714eb09e..86bd5413a9 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -529,9 +529,6 @@ int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc); void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now); int manager_ref_gid(Manager *m, gid_t gid, bool destroy_now); -void manager_vacuum_uid_refs(Manager *m); -void manager_vacuum_gid_refs(Manager *m); - void manager_serialize_uid_refs(Manager *m, FILE *f); void manager_deserialize_uid_refs_one(Manager *m, const char *value); From 80f605c807185e915a229fdde433c8a4c57f69ad Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Mon, 27 Apr 2020 08:59:43 +0200 Subject: [PATCH 5/6] pid1: make manager_serialize_{uid,gid}_refs() static No functional change. --- src/core/manager.c | 82 +++++++++++++++++++++++----------------------- src/core/manager.h | 3 -- 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index b9aeb0e515..e4bd70d724 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -3150,6 +3150,47 @@ static bool manager_timestamp_shall_serialize(ManagerTimestamp t) { MANAGER_TIMESTAMP_UNITS_LOAD_START, MANAGER_TIMESTAMP_UNITS_LOAD_FINISH); } +#define DESTROY_IPC_FLAG (UINT32_C(1) << 31) + +static void manager_serialize_uid_refs_internal( + Manager *m, + FILE *f, + Hashmap **uid_refs, + const char *field_name) { + + Iterator i; + void *p, *k; + + assert(m); + assert(f); + assert(uid_refs); + assert(field_name); + + /* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as + * the actual counter of it is better rebuild after a reload/reexec. */ + + HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) { + uint32_t c; + uid_t uid; + + uid = PTR_TO_UID(k); + c = PTR_TO_UINT32(p); + + if (!(c & DESTROY_IPC_FLAG)) + continue; + + (void) serialize_item_format(f, field_name, UID_FMT, uid); + } +} + +static void manager_serialize_uid_refs(Manager *m, FILE *f) { + manager_serialize_uid_refs_internal(m, f, &m->uid_refs, "destroy-ipc-uid"); +} + +static void manager_serialize_gid_refs(Manager *m, FILE *f) { + manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid"); +} + int manager_serialize( Manager *m, FILE *f, @@ -4383,8 +4424,6 @@ ManagerState manager_state(Manager *m) { return MANAGER_RUNNING; } -#define DESTROY_IPC_FLAG (UINT32_C(1) << 31) - static void manager_unref_uid_internal( Manager *m, Hashmap **uid_refs, @@ -4545,45 +4584,6 @@ static void manager_vacuum(Manager *m) { exec_runtime_vacuum(m); } -static void manager_serialize_uid_refs_internal( - Manager *m, - FILE *f, - Hashmap **uid_refs, - const char *field_name) { - - Iterator i; - void *p, *k; - - assert(m); - assert(f); - assert(uid_refs); - assert(field_name); - - /* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as the actual counter - * of it is better rebuild after a reload/reexec. */ - - HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) { - uint32_t c; - uid_t uid; - - uid = PTR_TO_UID(k); - c = PTR_TO_UINT32(p); - - if (!(c & DESTROY_IPC_FLAG)) - continue; - - (void) serialize_item_format(f, field_name, UID_FMT, uid); - } -} - -void manager_serialize_uid_refs(Manager *m, FILE *f) { - manager_serialize_uid_refs_internal(m, f, &m->uid_refs, "destroy-ipc-uid"); -} - -void manager_serialize_gid_refs(Manager *m, FILE *f) { - manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid"); -} - static void manager_deserialize_uid_refs_one_internal( Manager *m, Hashmap** uid_refs, diff --git a/src/core/manager.h b/src/core/manager.h index 86bd5413a9..80819dbdb1 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -529,10 +529,7 @@ int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc); void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now); int manager_ref_gid(Manager *m, gid_t gid, bool destroy_now); -void manager_serialize_uid_refs(Manager *m, FILE *f); void manager_deserialize_uid_refs_one(Manager *m, const char *value); - -void manager_serialize_gid_refs(Manager *m, FILE *f); void manager_deserialize_gid_refs_one(Manager *m, const char *value); char *manager_taint_string(Manager *m); From b406c6d12816439ffb5375e2751433bd2aca2e20 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Mon, 27 Apr 2020 09:01:18 +0200 Subject: [PATCH 6/6] pid1: make manager_deserialize_{uid,gid}_refs() static No functional change. --- src/core/manager.c | 92 +++++++++++++++++++++++----------------------- src/core/manager.h | 3 -- 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index e4bd70d724..ac5a3b6805 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -3427,6 +3427,52 @@ int manager_set_watchdog_overridden(Manager *m, WatchdogType t, usec_t timeout) return 0; } +static void manager_deserialize_uid_refs_one_internal( + Manager *m, + Hashmap** uid_refs, + const char *value) { + + uid_t uid; + uint32_t c; + int r; + + assert(m); + assert(uid_refs); + assert(value); + + r = parse_uid(value, &uid); + if (r < 0 || uid == 0) { + log_debug("Unable to parse UID reference serialization: " UID_FMT, uid); + return; + } + + r = hashmap_ensure_allocated(uid_refs, &trivial_hash_ops); + if (r < 0) { + log_oom(); + return; + } + + c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid))); + if (c & DESTROY_IPC_FLAG) + return; + + c |= DESTROY_IPC_FLAG; + + r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)); + if (r < 0) { + log_debug_errno(r, "Failed to add UID reference entry: %m"); + return; + } +} + +static void manager_deserialize_uid_refs_one(Manager *m, const char *value) { + manager_deserialize_uid_refs_one_internal(m, &m->uid_refs, value); +} + +static void manager_deserialize_gid_refs_one(Manager *m, const char *value) { + manager_deserialize_uid_refs_one_internal(m, &m->gid_refs, value); +} + int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { int r = 0; @@ -4584,52 +4630,6 @@ static void manager_vacuum(Manager *m) { exec_runtime_vacuum(m); } -static void manager_deserialize_uid_refs_one_internal( - Manager *m, - Hashmap** uid_refs, - const char *value) { - - uid_t uid; - uint32_t c; - int r; - - assert(m); - assert(uid_refs); - assert(value); - - r = parse_uid(value, &uid); - if (r < 0 || uid == 0) { - log_debug("Unable to parse UID reference serialization: " UID_FMT, uid); - return; - } - - r = hashmap_ensure_allocated(uid_refs, &trivial_hash_ops); - if (r < 0) { - log_oom(); - return; - } - - c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid))); - if (c & DESTROY_IPC_FLAG) - return; - - c |= DESTROY_IPC_FLAG; - - r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)); - if (r < 0) { - log_debug_errno(r, "Failed to add UID reference entry: %m"); - return; - } -} - -void manager_deserialize_uid_refs_one(Manager *m, const char *value) { - manager_deserialize_uid_refs_one_internal(m, &m->uid_refs, value); -} - -void manager_deserialize_gid_refs_one(Manager *m, const char *value) { - manager_deserialize_uid_refs_one_internal(m, &m->gid_refs, value); -} - int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { struct buffer { uid_t uid; diff --git a/src/core/manager.h b/src/core/manager.h index 80819dbdb1..a29d976eae 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -529,9 +529,6 @@ int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc); void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now); int manager_ref_gid(Manager *m, gid_t gid, bool destroy_now); -void manager_deserialize_uid_refs_one(Manager *m, const char *value); -void manager_deserialize_gid_refs_one(Manager *m, const char *value); - char *manager_taint_string(Manager *m); void manager_ref_console(Manager *m);