diff options
Diffstat (limited to 'src/login/logind.c')
-rw-r--r-- | src/login/logind.c | 225 |
1 files changed, 105 insertions, 120 deletions
diff --git a/src/login/logind.c b/src/login/logind.c index 5220861c1d..52fcee933c 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2011 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ #include <errno.h> #include <fcntl.h> @@ -30,60 +12,31 @@ #include "bus-error.h" #include "bus-util.h" #include "cgroup-util.h" -#include "conf-parser.h" #include "def.h" #include "dirent-util.h" #include "fd-util.h" #include "format-util.h" #include "fs-util.h" #include "logind.h" +#include "parse-util.h" #include "process-util.h" #include "selinux-util.h" #include "signal-util.h" #include "strv.h" #include "udev-util.h" -static void manager_free(Manager *m); - -static void manager_reset_config(Manager *m) { - m->n_autovts = 6; - m->reserve_vt = 6; - m->remove_ipc = true; - m->inhibit_delay_max = 5 * USEC_PER_SEC; - m->handle_power_key = HANDLE_POWEROFF; - m->handle_suspend_key = HANDLE_SUSPEND; - m->handle_hibernate_key = HANDLE_HIBERNATE; - m->handle_lid_switch = HANDLE_SUSPEND; - m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID; - m->handle_lid_switch_docked = HANDLE_IGNORE; - m->power_key_ignore_inhibited = false; - m->suspend_key_ignore_inhibited = false; - m->hibernate_key_ignore_inhibited = false; - m->lid_switch_ignore_inhibited = true; - - m->holdoff_timeout_usec = 30 * USEC_PER_SEC; - - m->idle_action_usec = 30 * USEC_PER_MINUTE; - m->idle_action = HANDLE_IGNORE; - - m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */ - m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */ - m->sessions_max = 8192; - m->inhibitors_max = 8192; - - m->kill_user_processes = KILL_USER_PROCESSES; - - m->kill_only_users = strv_free(m->kill_only_users); - m->kill_exclude_users = strv_free(m->kill_exclude_users); -} +static Manager* manager_unref(Manager *m); +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); -static Manager *manager_new(void) { - Manager *m; +static int manager_new(Manager **ret) { + _cleanup_(manager_unrefp) Manager *m = NULL; int r; + assert(ret); + m = new0(Manager, 1); if (!m) - return NULL; + return -ENOMEM; m->console_active_fd = -1; m->reserve_vt_fd = -1; @@ -101,28 +54,33 @@ static Manager *manager_new(void) { m->session_units = hashmap_new(&string_hash_ops); if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units) - goto fail; + return -ENOMEM; m->udev = udev_new(); if (!m->udev) - goto fail; + return -errno; r = sd_event_default(&m->event); if (r < 0) - goto fail; + return r; - sd_event_set_watchdog(m->event, true); + r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); + if (r < 0) + return r; - manager_reset_config(m); + r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); + if (r < 0) + return r; - return m; + (void) sd_event_set_watchdog(m->event, true); + + manager_reset_config(m); -fail: - manager_free(m); - return NULL; + *ret = TAKE_PTR(m); + return 0; } -static void manager_free(Manager *m) { +static Manager* manager_unref(Manager *m) { Session *session; User *u; Device *d; @@ -131,7 +89,7 @@ static void manager_free(Manager *m) { Button *b; if (!m) - return; + return NULL; while ((session = hashmap_first(m->sessions))) session_free(session); @@ -200,12 +158,13 @@ static void manager_free(Manager *m) { free(m->scheduled_shutdown_tty); free(m->wall_message); free(m->action_job); - free(m); + + return mfree(m); } static int manager_enumerate_devices(Manager *m) { struct udev_list_entry *item = NULL, *first = NULL; - _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; + _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL; int r; assert(m); @@ -231,7 +190,7 @@ static int manager_enumerate_devices(Manager *m) { first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { - _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_(udev_device_unrefp) struct udev_device *d = NULL; int k; d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item)); @@ -247,7 +206,7 @@ static int manager_enumerate_devices(Manager *m) { } static int manager_enumerate_buttons(Manager *m) { - _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; + _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; int r; @@ -280,7 +239,7 @@ static int manager_enumerate_buttons(Manager *m) { first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { - _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_(udev_device_unrefp) struct udev_device *d = NULL; int k; d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item)); @@ -411,6 +370,41 @@ static int manager_enumerate_users(Manager *m) { return r; } +static int parse_fdname(const char *fdname, char **session_id, dev_t *dev) { + _cleanup_strv_free_ char **parts = NULL; + _cleanup_free_ char *id = NULL; + unsigned int major, minor; + int r; + + parts = strv_split(fdname, "-"); + if (!parts) + return -ENOMEM; + if (strv_length(parts) != 5) + return -EINVAL; + + if (!streq(parts[0], "session")) + return -EINVAL; + + id = strdup(parts[1]); + if (!id) + return -ENOMEM; + + if (!streq(parts[2], "device")) + return -EINVAL; + + r = safe_atou(parts[3], &major); + if (r < 0) + return r; + r = safe_atou(parts[4], &minor); + if (r < 0) + return r; + + *dev = makedev(major, minor); + *session_id = TAKE_PTR(id); + + return 0; +} + static int manager_attach_fds(Manager *m) { _cleanup_strv_free_ char **fdnames = NULL; int n, i, fd; @@ -424,16 +418,21 @@ static int manager_attach_fds(Manager *m) { return n; for (i = 0; i < n; i++) { + _cleanup_free_ char *id = NULL; + dev_t dev; struct stat st; SessionDevice *sd; Session *s; - char *id; + int r; fd = SD_LISTEN_FDS_START + i; - id = startswith(fdnames[i], "session-"); - if (!id) + r = parse_fdname(fdnames[i], &id, &dev); + if (r < 0) { + log_debug_errno(r, "Failed to parse fd name %s: %m", fdnames[i]); + close_nointr(fd); continue; + } s = hashmap_get(m->sessions, id); if (!s) { @@ -453,24 +452,24 @@ static int manager_attach_fds(Manager *m) { continue; } - if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) { - log_debug("Device fd doesn't actually point to device node: %m"); + if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) { + log_debug("Device fd doesn't point to the expected character device node"); close_nointr(fd); continue; } - sd = hashmap_get(s->devices, &st.st_rdev); + sd = hashmap_get(s->devices, &dev); if (!sd) { /* Weird, we got an fd for a session device which wasn't - * recorded in the session state file... */ + * recorded in the session state file... */ log_warning("Got fd for missing session device [%u:%u] in session %s", - major(st.st_rdev), minor(st.st_rdev), s->id); + major(dev), minor(dev), s->id); close_nointr(fd); continue; } log_debug("Attaching fd to session device [%u:%u] for session %s", - major(st.st_rdev), minor(st.st_rdev), s->id); + major(dev), minor(dev), s->id); session_device_attach_fd(sd, fd, s->was_active); } @@ -567,7 +566,7 @@ static int manager_enumerate_inhibitors(Manager *m) { } static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_(udev_device_unrefp) struct udev_device *d = NULL; Manager *m = userdata; assert(m); @@ -581,7 +580,7 @@ static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t reven } static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_(udev_device_unrefp) struct udev_device *d = NULL; Manager *m = userdata; assert(m); @@ -595,7 +594,7 @@ static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t rev } static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_(udev_device_unrefp) struct udev_device *d = NULL; Manager *m = userdata; const char *name; @@ -617,7 +616,7 @@ static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t reven } static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_(udev_device_unrefp) struct udev_device *d = NULL; Manager *m = userdata; assert(m); @@ -1067,16 +1066,6 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us return 0; } -static int manager_parse_config_file(Manager *m) { - assert(m); - - return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf", - CONF_PATHS_NULSTR("systemd/logind.conf.d"), - "Login\0", - config_item_perf_lookup, logind_gperf_lookup, - CONFIG_PARSE_WARN, m); -} - static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { Manager *m = userdata; int r; @@ -1102,8 +1091,6 @@ static int manager_startup(Manager *m) { assert(m); - assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0); - r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m); if (r < 0) return log_error_errno(r, "Failed to register SIGHUP handler: %m"); @@ -1171,7 +1158,7 @@ static int manager_startup(Manager *m) { user_start(user); HASHMAP_FOREACH(session, m->sessions, i) - session_start(session); + session_start(session, NULL); HASHMAP_FOREACH(inhibitor, m->inhibitors, i) inhibitor_start(inhibitor); @@ -1211,7 +1198,7 @@ static int manager_run(Manager *m) { } int main(int argc, char *argv[]) { - Manager *m = NULL; + _cleanup_(manager_unrefp) Manager *m = NULL; int r; log_set_target(LOG_TARGET_AUTO); @@ -1233,22 +1220,22 @@ int main(int argc, char *argv[]) { goto finish; } - /* Always create the directories people can create inotify - * watches in. Note that some applications might check for the - * existence of /run/systemd/seats/ to determine whether - * logind is available, so please always make sure this check - * stays in. */ - mkdir_label("/run/systemd/seats", 0755); - mkdir_label("/run/systemd/users", 0755); - mkdir_label("/run/systemd/sessions", 0755); - - m = manager_new(); - if (!m) { - r = log_oom(); + /* Always create the directories people can create inotify watches in. Note that some applications might check + * for the existence of /run/systemd/seats/ to determine whether logind is available, so please always make + * sure these directories are created early on and unconditionally. */ + (void) mkdir_label("/run/systemd/seats", 0755); + (void) mkdir_label("/run/systemd/users", 0755); + (void) mkdir_label("/run/systemd/sessions", 0755); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGHUP, SIGTERM, SIGINT, -1) >= 0); + + r = manager_new(&m); + if (r < 0) { + log_error_errno(r, "Failed to allocate manager object: %m"); goto finish; } - manager_parse_config_file(m); + (void) manager_parse_config_file(m); r = manager_startup(m); if (r < 0) { @@ -1258,20 +1245,18 @@ int main(int argc, char *argv[]) { log_debug("systemd-logind running as pid "PID_FMT, getpid_cached()); - sd_notify(false, - "READY=1\n" - "STATUS=Processing requests..."); + (void) sd_notify(false, + "READY=1\n" + "STATUS=Processing requests..."); r = manager_run(m); log_debug("systemd-logind stopped as pid "PID_FMT, getpid_cached()); -finish: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); - - manager_free(m); + (void) sd_notify(false, + "STOPPING=1\n" + "STATUS=Shutting down..."); +finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } |