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(u->service_job);
553 u->service_job = job;
559 static int user_remove_runtime_path(User *u) {
564 r = rm_rf(u->runtime_path, 0);
566 log_error_errno(r, "Failed to remove runtime directory %s (before unmounting): %m", u->runtime_path);
568 /* Ignore cases where the directory isn't mounted, as that's
569 * quite possible, if we lacked the permissions to mount
571 r = umount2(u->runtime_path, MNT_DETACH);
572 if (r < 0 && !IN_SET(errno, EINVAL, ENOENT))
573 log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
575 r = rm_rf(u->runtime_path, REMOVE_ROOT);
577 log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", u->runtime_path);
582 int user_stop(User *u, bool force) {
587 /* Stop jobs have already been queued */
593 LIST_FOREACH(sessions_by_user, s, u->sessions) {
594 k = session_stop(s, force);
600 #if 0 /// elogind does not support service or slice jobs
601 k = user_stop_service(u);
606 k = user_stop_slice(u);
615 #if 1 /// elogind must queue this user again
616 user_add_to_gc_queue(u);
621 int user_finalize(User *u) {
628 log_debug("User %s logged out.", u->name);
630 LIST_FOREACH(sessions_by_user, s, u->sessions) {
631 k = session_finalize(s);
636 /* Kill XDG_RUNTIME_DIR */
637 k = user_remove_runtime_path(u);
641 /* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs
642 * are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to
643 * system components. Since enable RemoveIPC= globally for all users, we need to be a bit careful with such
644 * cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because
645 * a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up,
646 * and do it only for normal users. */
647 if (u->manager->remove_ipc && !uid_is_system(u->uid)) {
648 k = clean_ipc_by_uid(u->uid);
653 unlink(u->state_file);
654 user_add_to_gc_queue(u);
657 user_send_signal(u, false);
664 int user_get_idle_hint(User *u, dual_timestamp *t) {
666 bool idle_hint = true;
667 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
671 LIST_FOREACH(sessions_by_user, s, u->sessions) {
675 ih = session_get_idle_hint(s, &k);
681 if (k.monotonic < ts.monotonic)
687 } else if (idle_hint) {
689 if (k.monotonic > ts.monotonic)
700 int user_check_linger_file(User *u) {
701 _cleanup_free_ char *cc = NULL;
704 cc = cescape(u->name);
708 p = strjoina("/var/lib/elogind/linger/", cc);
710 return access(p, F_OK) >= 0;
713 bool user_check_gc(User *u, bool drop_not_started) {
716 if (drop_not_started && !u->started)
722 if (user_check_linger_file(u) > 0)
725 #if 0 /// elogind neither supports service nor slice jobs
726 if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
729 if (u->service_job && manager_job_is_active(u->manager, u->service_job))
736 void user_add_to_gc_queue(User *u) {
742 LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u);
743 u->in_gc_queue = true;
746 UserState user_get_state(User *u) {
754 #if 0 /// elogind neither supports service nor slice jobs.
755 if (!u->started || u->slice_job || u->service_job)
762 bool all_closing = true;
764 LIST_FOREACH(sessions_by_user, i, u->sessions) {
767 state = session_get_state(i);
768 if (state == SESSION_ACTIVE)
770 if (state != SESSION_CLOSING)
774 return all_closing ? USER_CLOSING : USER_ONLINE;
777 if (user_check_linger_file(u) > 0)
778 return USER_LINGERING;
783 int user_kill(User *u, int signo) {
784 #if 0 /// Without systemd unit support, elogind has to rely on its session system
787 return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
794 LIST_FOREACH(sessions_by_user, s, u->sessions) {
795 int r = session_kill(s, KILL_ALL, signo);
796 if (res == 0 && r < 0)
804 static bool elect_display_filter(Session *s) {
805 /* Return true if the session is a candidate for the user’s ‘primary
806 * session’ or ‘display’. */
809 return (s->class == SESSION_USER && !s->stopping);
812 static int elect_display_compare(Session *s1, Session *s2) {
813 /* Indexed by SessionType. Lower numbers mean more preferred. */
814 const int type_ranks[_SESSION_TYPE_MAX] = {
815 [SESSION_UNSPECIFIED] = 0,
818 [SESSION_WAYLAND] = -3,
823 /* Calculate the partial order relationship between s1 and s2,
824 * returning < 0 if s1 is preferred as the user’s ‘primary session’,
825 * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
828 * s1 or s2 may be NULL. */
832 if ((s1 == NULL) != (s2 == NULL))
833 return (s1 == NULL) - (s2 == NULL);
835 if (s1->stopping != s2->stopping)
836 return s1->stopping - s2->stopping;
838 if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
839 return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
841 if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
842 return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
844 if (s1->type != s2->type)
845 return type_ranks[s1->type] - type_ranks[s2->type];
850 void user_elect_display(User *u) {
855 /* This elects a primary session for each user, which we call
856 * the "display". We try to keep the assignment stable, but we
857 * "upgrade" to better choices. */
858 log_debug("Electing new display for user %s", u->name);
860 LIST_FOREACH(sessions_by_user, s, u->sessions) {
861 if (!elect_display_filter(s)) {
862 log_debug("Ignoring session %s", s->id);
866 if (elect_display_compare(s, u->display) < 0) {
867 log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
873 static const char* const user_state_table[_USER_STATE_MAX] = {
874 [USER_OFFLINE] = "offline",
875 [USER_OPENING] = "opening",
876 [USER_LINGERING] = "lingering",
877 [USER_ONLINE] = "online",
878 [USER_ACTIVE] = "active",
879 [USER_CLOSING] = "closing"
882 DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
884 int config_parse_tmpfs_size(
886 const char *filename,
889 unsigned section_line,
904 /* First, try to parse as percentage */
905 r = parse_percent(rvalue);
906 if (r > 0 && r < 100)
907 *sz = physical_memory_scale(r, 100U);
911 /* If the passed argument was not a percentage, or out of range, parse as byte size */
913 r = parse_size(rvalue, 1024, &k);
914 if (r < 0 || k <= 0 || (uint64_t) (size_t) k != k) {
915 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
919 *sz = PAGE_ALIGN((size_t) k);
925 int config_parse_user_tasks_max(
927 const char *filename,
930 unsigned section_line,
946 if (isempty(rvalue)) {
947 *m = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U);
951 if (streq(rvalue, "infinity")) {
952 *m = CGROUP_LIMIT_MAX;
956 /* Try to parse as percentage */
957 r = parse_percent(rvalue);
959 k = system_tasks_max_scale(r, 100U);
962 /* If the passed argument was not a percentage, or out of range, parse as byte size */
964 r = safe_atou64(rvalue, &k);
966 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse tasks maximum, ignoring: %s", rvalue);
971 if (k <= 0 || k >= UINT64_MAX) {
972 log_syntax(unit, LOG_ERR, filename, line, 0, "Tasks maximum out of range, ignoring: %s", rvalue);