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"
48 //#include "special.h"
49 #include "stdio-util.h"
50 #include "string-table.h"
51 #include "unit-name.h"
52 #include "user-util.h"
55 #if 1 /// elogind uses a static value here
56 # define SPECIAL_USER_SLICE "user.slice"
58 int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
59 _cleanup_(user_freep) User *u = NULL;
60 char lu[DECIMAL_STR_MAX(uid_t) + 1];
74 xsprintf(lu, UID_FMT, uid);
76 u->name = strdup(name);
80 if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
83 if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0)
86 r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice);
90 r = unit_name_build("user", lu, ".service", &u->service);
94 r = hashmap_put(m->users, UID_TO_PTR(uid), u);
98 r = hashmap_put(m->user_units, u->slice, u);
102 r = hashmap_put(m->user_units, u->service, u);
111 User *user_free(User *u) {
116 LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u);
119 session_free(u->sessions);
122 hashmap_remove_value(u->manager->user_units, u->service, u);
125 hashmap_remove_value(u->manager->user_units, u->slice, u);
127 hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u);
129 #if 0 /// elogind neither supports slice nor service jobs.
130 u->slice_job = mfree(u->slice_job);
131 u->service_job = mfree(u->service_job);
134 u->service = mfree(u->service);
135 u->slice = mfree(u->slice);
136 u->runtime_path = mfree(u->runtime_path);
137 u->state_file = mfree(u->state_file);
138 u->name = mfree(u->name);
143 static int user_save_internal(User *u) {
144 _cleanup_free_ char *temp_path = NULL;
145 _cleanup_fclose_ FILE *f = NULL;
149 assert(u->state_file);
151 r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, false);
155 r = fopen_temporary(u->state_file, &f, &temp_path);
159 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
160 (void) fchmod(fileno(f), 0644);
163 "# This is private data. Do not parse.\n"
167 user_state_to_string(user_get_state(u)));
169 /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */
171 fprintf(f, "RUNTIME=%s\n", u->runtime_path);
173 #if 0 /// elogind neither supports service nor slice jobs
175 fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
178 fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
182 fprintf(f, "DISPLAY=%s\n", u->display->id);
184 if (dual_timestamp_is_set(&u->timestamp))
186 "REALTIME="USEC_FMT"\n"
187 "MONOTONIC="USEC_FMT"\n",
188 u->timestamp.realtime,
189 u->timestamp.monotonic);
195 fputs("SESSIONS=", f);
197 LIST_FOREACH(sessions_by_user, i, u->sessions) {
206 fputs("\nSEATS=", f);
208 LIST_FOREACH(sessions_by_user, i, u->sessions) {
217 fputs(i->seat->id, f);
220 fputs("\nACTIVE_SESSIONS=", f);
222 LIST_FOREACH(sessions_by_user, i, u->sessions) {
223 if (!session_is_active(i))
234 fputs("\nONLINE_SESSIONS=", f);
236 LIST_FOREACH(sessions_by_user, i, u->sessions) {
237 if (session_get_state(i) == SESSION_CLOSING)
248 fputs("\nACTIVE_SEATS=", f);
250 LIST_FOREACH(sessions_by_user, i, u->sessions) {
251 if (!session_is_active(i) || !i->seat)
259 fputs(i->seat->id, f);
262 fputs("\nONLINE_SEATS=", f);
264 LIST_FOREACH(sessions_by_user, i, u->sessions) {
265 if (session_get_state(i) == SESSION_CLOSING || !i->seat)
273 fputs(i->seat->id, f);
278 r = fflush_and_check(f);
282 if (rename(temp_path, u->state_file) < 0) {
290 (void) unlink(u->state_file);
293 (void) unlink(temp_path);
295 return log_error_errno(r, "Failed to save user data %s: %m", u->state_file);
298 int user_save(User *u) {
304 return user_save_internal (u);
307 int user_load(User *u) {
308 _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
314 r = parse_env_file(u->state_file, NEWLINE,
315 #if 0 /// elogind neither supports service nor slice jobs
316 "SERVICE_JOB", &u->service_job,
317 "SLICE_JOB", &u->slice_job,
320 "REALTIME", &realtime,
321 "MONOTONIC", &monotonic,
327 return log_error_errno(r, "Failed to read %s: %m", u->state_file);
331 s = hashmap_get(u->manager->sessions, display);
333 if (s && s->display && display_is_local(s->display))
337 timestamp_deserialize(realtime, &u->timestamp.realtime);
339 timestamp_deserialize(monotonic, &u->timestamp.monotonic);
344 static int user_mkdir_runtime_path(User *u) {
349 r = mkdir_safe_label("/run/user", 0755, 0, 0, false);
351 return log_error_errno(r, "Failed to create /run/user: %m");
353 if (path_is_mount_point(u->runtime_path, NULL, 0) <= 0) {
354 _cleanup_free_ char *t = NULL;
356 r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s",
357 u->uid, u->gid, u->manager->runtime_dir_size,
358 mac_smack_use() ? ",smackfsroot=*" : "");
362 (void) mkdir_label(u->runtime_path, 0700);
364 r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t);
366 if (!IN_SET(errno, EPERM, EACCES)) {
367 r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path);
371 log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s, assuming containerized execution, ignoring: %m", u->runtime_path);
373 r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid);
375 log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
380 r = label_fix(u->runtime_path, false, false);
382 log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", u->runtime_path);
388 /* Try to clean up, but ignore errors */
389 (void) rmdir(u->runtime_path);
393 static int user_start_slice(User *u) {
394 #if 0 /// elogind can not ask systemd via dbus to start user services
395 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
396 const char *description;
402 u->slice_job = mfree(u->slice_job);
403 description = strjoina("User Slice of ", u->name);
405 r = manager_start_slice(
409 "systemd-logind.service",
410 "systemd-user-sessions.service",
411 u->manager->user_tasks_max,
416 else if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
417 /* we don't fail due to this, let's try to continue */
418 log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)",
419 u->slice, bus_error_message(&error, r), error.name);
423 hashmap_put(u->manager->user_units, u->slice, u);
429 static int user_start_service(User *u) {
430 #if 0 /// elogind can not ask systemd via dbus to start user services
431 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
437 u->service_job = mfree(u->service_job);
439 r = manager_start_unit(
445 /* we don't fail due to this, let's try to continue */
446 log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r));
448 u->service_job = job;
452 hashmap_put(u->manager->user_units, u->service, u);
458 int user_start(User *u) {
463 if (u->started && !u->stopping)
467 * If u->stopping is set, the user is marked for removal and the slice
468 * and service stop-jobs are queued. We have to clear that flag before
469 * queing the start-jobs again. If they succeed, the user object can be
470 * re-used just fine (pid1 takes care of job-ordering and proper
471 * restart), but if they fail, we want to force another user_stop() so
472 * possibly pending units are stopped.
473 * Note that we don't clear u->started, as we have no clue what state
474 * the user is in on failure here. Hence, we pretend the user is
475 * running so it will be properly taken down by GC. However, we clearly
476 * return an error from user_start() in that case, so no further
477 * reference to the user is taken.
482 log_debug("Starting services for new user %s.", u->name);
484 /* Make XDG_RUNTIME_DIR */
485 r = user_mkdir_runtime_path(u);
491 r = user_start_slice(u);
495 /* Save the user data so far, because pam_systemd will read the
496 * XDG_RUNTIME_DIR out of it while starting up systemd --user.
497 * We need to do user_save_internal() because we have not
498 * "officially" started yet. */
499 user_save_internal(u);
501 /* Spawn user systemd */
502 r = user_start_service(u);
507 if (!dual_timestamp_is_set(&u->timestamp))
508 dual_timestamp_get(&u->timestamp);
509 user_send_signal(u, true);
513 /* Save new user data */
519 #if 0 /// UNNEEDED by elogind
520 static int user_stop_slice(User *u) {
521 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
527 r = manager_stop_unit(u->manager, u->slice, &error, &job);
529 log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
539 static int user_stop_service(User *u) {
540 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
546 r = manager_stop_unit(u->manager, u->service, &error, &job);
548 log_error("Failed to stop user service: %s", bus_error_message(&error, r));
552 free_and_replace(u->service_job, job);
557 static int user_remove_runtime_path(User *u) {
562 r = rm_rf(u->runtime_path, 0);
564 log_error_errno(r, "Failed to remove runtime directory %s (before unmounting): %m", u->runtime_path);
566 /* Ignore cases where the directory isn't mounted, as that's
567 * quite possible, if we lacked the permissions to mount
569 r = umount2(u->runtime_path, MNT_DETACH);
570 if (r < 0 && !IN_SET(errno, EINVAL, ENOENT))
571 log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
573 r = rm_rf(u->runtime_path, REMOVE_ROOT);
575 log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", u->runtime_path);
580 int user_stop(User *u, bool force) {
585 /* Stop jobs have already been queued */
591 LIST_FOREACH(sessions_by_user, s, u->sessions) {
592 k = session_stop(s, force);
598 #if 0 /// elogind does not support service or slice jobs
599 k = user_stop_service(u);
604 k = user_stop_slice(u);
613 #if 1 /// elogind must queue this user again
614 user_add_to_gc_queue(u);
619 int user_finalize(User *u) {
626 log_debug("User %s logged out.", u->name);
628 LIST_FOREACH(sessions_by_user, s, u->sessions) {
629 k = session_finalize(s);
634 /* Kill XDG_RUNTIME_DIR */
635 k = user_remove_runtime_path(u);
639 /* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs
640 * are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to
641 * system components. Since enable RemoveIPC= globally for all users, we need to be a bit careful with such
642 * cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because
643 * a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up,
644 * and do it only for normal users. */
645 if (u->manager->remove_ipc && !uid_is_system(u->uid)) {
646 k = clean_ipc_by_uid(u->uid);
651 unlink(u->state_file);
652 user_add_to_gc_queue(u);
655 user_send_signal(u, false);
662 int user_get_idle_hint(User *u, dual_timestamp *t) {
664 bool idle_hint = true;
665 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
669 LIST_FOREACH(sessions_by_user, s, u->sessions) {
673 ih = session_get_idle_hint(s, &k);
679 if (k.monotonic < ts.monotonic)
685 } else if (idle_hint) {
687 if (k.monotonic > ts.monotonic)
698 int user_check_linger_file(User *u) {
699 _cleanup_free_ char *cc = NULL;
702 cc = cescape(u->name);
706 p = strjoina("/var/lib/elogind/linger/", cc);
708 return access(p, F_OK) >= 0;
711 bool user_check_gc(User *u, bool drop_not_started) {
714 if (drop_not_started && !u->started)
720 if (user_check_linger_file(u) > 0)
723 #if 0 /// elogind neither supports service nor slice jobs
724 if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
727 if (u->service_job && manager_job_is_active(u->manager, u->service_job))
734 void user_add_to_gc_queue(User *u) {
740 LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u);
741 u->in_gc_queue = true;
744 UserState user_get_state(User *u) {
752 #if 0 /// elogind neither supports service nor slice jobs.
753 if (!u->started || u->slice_job || u->service_job)
760 bool all_closing = true;
762 LIST_FOREACH(sessions_by_user, i, u->sessions) {
765 state = session_get_state(i);
766 if (state == SESSION_ACTIVE)
768 if (state != SESSION_CLOSING)
772 return all_closing ? USER_CLOSING : USER_ONLINE;
775 if (user_check_linger_file(u) > 0)
776 return USER_LINGERING;
781 int user_kill(User *u, int signo) {
782 #if 0 /// Without systemd unit support, elogind has to rely on its session system
785 return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
792 LIST_FOREACH(sessions_by_user, s, u->sessions) {
793 int r = session_kill(s, KILL_ALL, signo);
794 if (res == 0 && r < 0)
802 static bool elect_display_filter(Session *s) {
803 /* Return true if the session is a candidate for the user’s ‘primary
804 * session’ or ‘display’. */
807 return (s->class == SESSION_USER && !s->stopping);
810 static int elect_display_compare(Session *s1, Session *s2) {
811 /* Indexed by SessionType. Lower numbers mean more preferred. */
812 const int type_ranks[_SESSION_TYPE_MAX] = {
813 [SESSION_UNSPECIFIED] = 0,
816 [SESSION_WAYLAND] = -3,
821 /* Calculate the partial order relationship between s1 and s2,
822 * returning < 0 if s1 is preferred as the user’s ‘primary session’,
823 * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
826 * s1 or s2 may be NULL. */
830 if ((s1 == NULL) != (s2 == NULL))
831 return (s1 == NULL) - (s2 == NULL);
833 if (s1->stopping != s2->stopping)
834 return s1->stopping - s2->stopping;
836 if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
837 return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
839 if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
840 return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
842 if (s1->type != s2->type)
843 return type_ranks[s1->type] - type_ranks[s2->type];
848 void user_elect_display(User *u) {
853 /* This elects a primary session for each user, which we call
854 * the "display". We try to keep the assignment stable, but we
855 * "upgrade" to better choices. */
856 log_debug("Electing new display for user %s", u->name);
858 LIST_FOREACH(sessions_by_user, s, u->sessions) {
859 if (!elect_display_filter(s)) {
860 log_debug("Ignoring session %s", s->id);
864 if (elect_display_compare(s, u->display) < 0) {
865 log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
871 static const char* const user_state_table[_USER_STATE_MAX] = {
872 [USER_OFFLINE] = "offline",
873 [USER_OPENING] = "opening",
874 [USER_LINGERING] = "lingering",
875 [USER_ONLINE] = "online",
876 [USER_ACTIVE] = "active",
877 [USER_CLOSING] = "closing"
880 DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
882 int config_parse_tmpfs_size(
884 const char *filename,
887 unsigned section_line,
902 /* First, try to parse as percentage */
903 r = parse_percent(rvalue);
904 if (r > 0 && r < 100)
905 *sz = physical_memory_scale(r, 100U);
909 /* If the passed argument was not a percentage, or out of range, parse as byte size */
911 r = parse_size(rvalue, 1024, &k);
912 if (r < 0 || k <= 0 || (uint64_t) (size_t) k != k) {
913 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
917 *sz = PAGE_ALIGN((size_t) k);
923 int config_parse_user_tasks_max(
925 const char *filename,
928 unsigned section_line,
944 if (isempty(rvalue)) {
945 *m = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U);
949 if (streq(rvalue, "infinity")) {
950 *m = CGROUP_LIMIT_MAX;
954 /* Try to parse as percentage */
955 r = parse_percent(rvalue);
957 k = system_tasks_max_scale(r, 100U);
960 /* If the passed argument was not a percentage, or out of range, parse as byte size */
962 r = safe_atou64(rvalue, &k);
964 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse tasks maximum, ignoring: %s", rvalue);
969 if (k <= 0 || k >= UINT64_MAX) {
970 log_syntax(unit, LOG_ERR, filename, line, 0, "Tasks maximum out of range, ignoring: %s", rvalue);