1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2011 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/mount.h>
25 #include <stdio_ext.h>
27 #include "alloc-util.h"
28 #include "bus-common-errors.h"
29 #include "bus-error.h"
31 #include "cgroup-util.h"
32 #include "clean-ipc.h"
33 #include "conf-parser.h"
37 #include "format-util.h"
41 #include "logind-user.h"
43 #include "mount-util.h"
44 #include "parse-util.h"
45 #include "path-util.h"
47 #include "smack-util.h"
49 #include "stdio-util.h"
50 #include "string-table.h"
51 #include "unit-name.h"
52 #include "user-util.h"
55 int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
56 _cleanup_(user_freep) User *u = NULL;
57 char lu[DECIMAL_STR_MAX(uid_t) + 1];
71 xsprintf(lu, UID_FMT, uid);
73 u->name = strdup(name);
77 if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
80 if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0)
83 r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice);
87 r = unit_name_build("user", lu, ".service", &u->service);
91 r = hashmap_put(m->users, UID_TO_PTR(uid), u);
95 r = hashmap_put(m->user_units, u->slice, u);
99 r = hashmap_put(m->user_units, u->service, u);
108 User *user_free(User *u) {
113 LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u);
116 session_free(u->sessions);
119 hashmap_remove_value(u->manager->user_units, u->service, u);
122 hashmap_remove_value(u->manager->user_units, u->slice, u);
124 hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u);
126 #if 0 /// elogind neither supports slice nor service jobs.
127 u->slice_job = mfree(u->slice_job);
128 u->service_job = mfree(u->service_job);
131 u->service = mfree(u->service);
132 u->slice = mfree(u->slice);
133 u->runtime_path = mfree(u->runtime_path);
134 u->state_file = mfree(u->state_file);
135 u->name = mfree(u->name);
140 static int user_save_internal(User *u) {
141 _cleanup_free_ char *temp_path = NULL;
142 _cleanup_fclose_ FILE *f = NULL;
146 assert(u->state_file);
148 r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, MKDIR_WARN_MODE);
152 r = fopen_temporary(u->state_file, &f, &temp_path);
156 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
157 (void) fchmod(fileno(f), 0644);
160 "# This is private data. Do not parse.\n"
164 user_state_to_string(user_get_state(u)));
166 /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */
168 fprintf(f, "RUNTIME=%s\n", u->runtime_path);
170 #if 0 /// elogind neither supports service nor slice jobs
172 fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
175 fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
179 fprintf(f, "DISPLAY=%s\n", u->display->id);
181 if (dual_timestamp_is_set(&u->timestamp))
183 "REALTIME="USEC_FMT"\n"
184 "MONOTONIC="USEC_FMT"\n",
185 u->timestamp.realtime,
186 u->timestamp.monotonic);
192 fputs("SESSIONS=", f);
194 LIST_FOREACH(sessions_by_user, i, u->sessions) {
203 fputs("\nSEATS=", f);
205 LIST_FOREACH(sessions_by_user, i, u->sessions) {
214 fputs(i->seat->id, f);
217 fputs("\nACTIVE_SESSIONS=", f);
219 LIST_FOREACH(sessions_by_user, i, u->sessions) {
220 if (!session_is_active(i))
231 fputs("\nONLINE_SESSIONS=", f);
233 LIST_FOREACH(sessions_by_user, i, u->sessions) {
234 if (session_get_state(i) == SESSION_CLOSING)
245 fputs("\nACTIVE_SEATS=", f);
247 LIST_FOREACH(sessions_by_user, i, u->sessions) {
248 if (!session_is_active(i) || !i->seat)
256 fputs(i->seat->id, f);
259 fputs("\nONLINE_SEATS=", f);
261 LIST_FOREACH(sessions_by_user, i, u->sessions) {
262 if (session_get_state(i) == SESSION_CLOSING || !i->seat)
270 fputs(i->seat->id, f);
275 r = fflush_and_check(f);
279 if (rename(temp_path, u->state_file) < 0) {
287 (void) unlink(u->state_file);
290 (void) unlink(temp_path);
292 return log_error_errno(r, "Failed to save user data %s: %m", u->state_file);
295 int user_save(User *u) {
301 return user_save_internal (u);
304 int user_load(User *u) {
305 _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
311 r = parse_env_file(u->state_file, NEWLINE,
312 #if 0 /// elogind neither supports service nor slice jobs
313 "SERVICE_JOB", &u->service_job,
314 "SLICE_JOB", &u->slice_job,
317 "REALTIME", &realtime,
318 "MONOTONIC", &monotonic,
324 return log_error_errno(r, "Failed to read %s: %m", u->state_file);
328 s = hashmap_get(u->manager->sessions, display);
330 if (s && s->display && display_is_local(s->display))
334 timestamp_deserialize(realtime, &u->timestamp.realtime);
336 timestamp_deserialize(monotonic, &u->timestamp.monotonic);
341 static int user_mkdir_runtime_path(User *u) {
346 r = mkdir_safe_label("/run/user", 0755, 0, 0, MKDIR_WARN_MODE);
348 return log_error_errno(r, "Failed to create /run/user: %m");
350 if (path_is_mount_point(u->runtime_path, NULL, 0) <= 0) {
351 _cleanup_free_ char *t = NULL;
353 r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s",
354 u->uid, u->gid, u->manager->runtime_dir_size,
355 mac_smack_use() ? ",smackfsroot=*" : "");
359 (void) mkdir_label(u->runtime_path, 0700);
361 r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t);
363 if (!IN_SET(errno, EPERM, EACCES)) {
364 r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path);
368 log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s, assuming containerized execution, ignoring: %m", u->runtime_path);
370 r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid);
372 log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
377 r = label_fix(u->runtime_path, 0);
379 log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", u->runtime_path);
385 /* Try to clean up, but ignore errors */
386 (void) rmdir(u->runtime_path);
390 static int user_start_slice(User *u) {
391 #if 0 /// elogind can not ask systemd via dbus to start user services
392 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
393 const char *description;
399 u->slice_job = mfree(u->slice_job);
400 description = strjoina("User Slice of ", u->name);
402 r = manager_start_slice(
406 "systemd-logind.service",
407 "systemd-user-sessions.service",
408 u->manager->user_tasks_max,
413 else if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
414 /* we don't fail due to this, let's try to continue */
415 log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)",
416 u->slice, bus_error_message(&error, r), error.name);
420 hashmap_put(u->manager->user_units, u->slice, u);
426 static int user_start_service(User *u) {
427 #if 0 /// elogind can not ask systemd via dbus to start user services
428 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
434 u->service_job = mfree(u->service_job);
436 r = manager_start_unit(
442 /* we don't fail due to this, let's try to continue */
443 log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r));
445 u->service_job = job;
449 hashmap_put(u->manager->user_units, u->service, u);
455 int user_start(User *u) {
460 if (u->started && !u->stopping)
464 * If u->stopping is set, the user is marked for removal and the slice
465 * and service stop-jobs are queued. We have to clear that flag before
466 * queing the start-jobs again. If they succeed, the user object can be
467 * re-used just fine (pid1 takes care of job-ordering and proper
468 * restart), but if they fail, we want to force another user_stop() so
469 * possibly pending units are stopped.
470 * Note that we don't clear u->started, as we have no clue what state
471 * the user is in on failure here. Hence, we pretend the user is
472 * running so it will be properly taken down by GC. However, we clearly
473 * return an error from user_start() in that case, so no further
474 * reference to the user is taken.
479 log_debug("Starting services for new user %s.", u->name);
481 /* Make XDG_RUNTIME_DIR */
482 r = user_mkdir_runtime_path(u);
488 r = user_start_slice(u);
492 /* Save the user data so far, because pam_systemd will read the
493 * XDG_RUNTIME_DIR out of it while starting up systemd --user.
494 * We need to do user_save_internal() because we have not
495 * "officially" started yet. */
496 user_save_internal(u);
498 /* Spawn user systemd */
499 r = user_start_service(u);
504 if (!dual_timestamp_is_set(&u->timestamp))
505 dual_timestamp_get(&u->timestamp);
506 user_send_signal(u, true);
510 /* Save new user data */
516 #if 0 /// UNNEEDED by elogind
517 static int user_stop_slice(User *u) {
518 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
524 r = manager_stop_unit(u->manager, u->slice, &error, &job);
526 log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
536 static int user_stop_service(User *u) {
537 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
543 r = manager_stop_unit(u->manager, u->service, &error, &job);
545 log_error("Failed to stop user service: %s", bus_error_message(&error, r));
549 free_and_replace(u->service_job, job);
554 static int user_remove_runtime_path(User *u) {
559 r = rm_rf(u->runtime_path, 0);
561 log_error_errno(r, "Failed to remove runtime directory %s (before unmounting): %m", u->runtime_path);
563 /* Ignore cases where the directory isn't mounted, as that's
564 * quite possible, if we lacked the permissions to mount
566 r = umount2(u->runtime_path, MNT_DETACH);
567 if (r < 0 && !IN_SET(errno, EINVAL, ENOENT))
568 log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
570 r = rm_rf(u->runtime_path, REMOVE_ROOT);
572 log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", u->runtime_path);
577 int user_stop(User *u, bool force) {
582 /* Stop jobs have already been queued */
588 LIST_FOREACH(sessions_by_user, s, u->sessions) {
589 k = session_stop(s, force);
595 #if 0 /// elogind does not support service or slice jobs
596 k = user_stop_service(u);
601 k = user_stop_slice(u);
610 #if 1 /// elogind must queue this user again
611 user_add_to_gc_queue(u);
616 int user_finalize(User *u) {
623 log_debug("User %s logged out.", u->name);
625 LIST_FOREACH(sessions_by_user, s, u->sessions) {
626 k = session_finalize(s);
631 /* Kill XDG_RUNTIME_DIR */
632 k = user_remove_runtime_path(u);
636 /* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs
637 * are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to
638 * system components. Since enable RemoveIPC= globally for all users, we need to be a bit careful with such
639 * cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because
640 * a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up,
641 * and do it only for normal users. */
642 if (u->manager->remove_ipc && !uid_is_system(u->uid)) {
643 k = clean_ipc_by_uid(u->uid);
648 unlink(u->state_file);
649 user_add_to_gc_queue(u);
652 user_send_signal(u, false);
659 int user_get_idle_hint(User *u, dual_timestamp *t) {
661 bool idle_hint = true;
662 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
666 LIST_FOREACH(sessions_by_user, s, u->sessions) {
670 ih = session_get_idle_hint(s, &k);
676 if (k.monotonic < ts.monotonic)
682 } else if (idle_hint) {
684 if (k.monotonic > ts.monotonic)
695 int user_check_linger_file(User *u) {
696 _cleanup_free_ char *cc = NULL;
699 cc = cescape(u->name);
703 p = strjoina("/var/lib/elogind/linger/", cc);
705 return access(p, F_OK) >= 0;
708 bool user_may_gc(User *u, bool drop_not_started) {
711 if (drop_not_started && !u->started)
717 if (user_check_linger_file(u) > 0)
720 #if 0 /// elogind neither supports service nor slice jobs
721 if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
724 if (u->service_job && manager_job_is_active(u->manager, u->service_job))
731 void user_add_to_gc_queue(User *u) {
737 LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u);
738 u->in_gc_queue = true;
741 UserState user_get_state(User *u) {
749 #if 0 /// elogind neither supports service nor slice jobs.
750 if (!u->started || u->slice_job || u->service_job)
757 bool all_closing = true;
759 LIST_FOREACH(sessions_by_user, i, u->sessions) {
762 state = session_get_state(i);
763 if (state == SESSION_ACTIVE)
765 if (state != SESSION_CLOSING)
769 return all_closing ? USER_CLOSING : USER_ONLINE;
772 if (user_check_linger_file(u) > 0)
773 return USER_LINGERING;
778 int user_kill(User *u, int signo) {
779 #if 0 /// Without systemd unit support, elogind has to rely on its session system
782 return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
789 LIST_FOREACH(sessions_by_user, s, u->sessions) {
790 int r = session_kill(s, KILL_ALL, signo);
791 if (res == 0 && r < 0)
799 static bool elect_display_filter(Session *s) {
800 /* Return true if the session is a candidate for the user’s ‘primary
801 * session’ or ‘display’. */
804 return (s->class == SESSION_USER && !s->stopping);
807 static int elect_display_compare(Session *s1, Session *s2) {
808 /* Indexed by SessionType. Lower numbers mean more preferred. */
809 const int type_ranks[_SESSION_TYPE_MAX] = {
810 [SESSION_UNSPECIFIED] = 0,
813 [SESSION_WAYLAND] = -3,
818 /* Calculate the partial order relationship between s1 and s2,
819 * returning < 0 if s1 is preferred as the user’s ‘primary session’,
820 * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
823 * s1 or s2 may be NULL. */
827 if ((s1 == NULL) != (s2 == NULL))
828 return (s1 == NULL) - (s2 == NULL);
830 if (s1->stopping != s2->stopping)
831 return s1->stopping - s2->stopping;
833 if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
834 return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
836 if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
837 return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
839 if (s1->type != s2->type)
840 return type_ranks[s1->type] - type_ranks[s2->type];
845 void user_elect_display(User *u) {
850 /* This elects a primary session for each user, which we call
851 * the "display". We try to keep the assignment stable, but we
852 * "upgrade" to better choices. */
853 log_debug("Electing new display for user %s", u->name);
855 LIST_FOREACH(sessions_by_user, s, u->sessions) {
856 if (!elect_display_filter(s)) {
857 log_debug("Ignoring session %s", s->id);
861 if (elect_display_compare(s, u->display) < 0) {
862 log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
868 static const char* const user_state_table[_USER_STATE_MAX] = {
869 [USER_OFFLINE] = "offline",
870 [USER_OPENING] = "opening",
871 [USER_LINGERING] = "lingering",
872 [USER_ONLINE] = "online",
873 [USER_ACTIVE] = "active",
874 [USER_CLOSING] = "closing"
877 DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
879 int config_parse_tmpfs_size(
881 const char *filename,
884 unsigned section_line,
899 /* First, try to parse as percentage */
900 r = parse_percent(rvalue);
901 if (r > 0 && r < 100)
902 *sz = physical_memory_scale(r, 100U);
906 /* If the passed argument was not a percentage, or out of range, parse as byte size */
908 r = parse_size(rvalue, 1024, &k);
909 if (r < 0 || k <= 0 || (uint64_t) (size_t) k != k) {
910 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
914 *sz = PAGE_ALIGN((size_t) k);
920 int config_parse_user_tasks_max(
922 const char *filename,
925 unsigned section_line,
941 if (isempty(rvalue)) {
942 *m = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U);
946 if (streq(rvalue, "infinity")) {
947 *m = CGROUP_LIMIT_MAX;
951 /* Try to parse as percentage */
952 r = parse_percent(rvalue);
954 k = system_tasks_max_scale(r, 100U);
957 /* If the passed argument was not a percentage, or out of range, parse as byte size */
959 r = safe_atou64(rvalue, &k);
961 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse tasks maximum, ignoring: %s", rvalue);
966 if (k <= 0 || k >= UINT64_MAX) {
967 log_syntax(unit, LOG_ERR, filename, line, 0, "Tasks maximum out of range, ignoring: %s", rvalue);