1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/mount.h>
32 #include "path-util.h"
33 // #include "special.h"
34 #include "unit-name.h"
36 #include "bus-error.h"
37 #include "conf-parser.h"
38 #include "clean-ipc.h"
39 #include "smack-util.h"
40 #include "formats-util.h"
42 #include "logind-user.h"
44 User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
54 u->name = strdup(name);
58 if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
61 if (hashmap_put(m->users, UID_TO_PTR(uid), u) < 0)
78 void user_free(User *u) {
82 LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u);
85 session_free(u->sessions);
88 hashmap_remove(u->manager->user_units, u->slice);
93 hashmap_remove(u->manager->user_units, u->service);
97 /// elogind does not support slice and service jobs
100 free(u->service_job);
103 free(u->runtime_path);
105 hashmap_remove(u->manager->users, UID_TO_PTR(u->uid));
112 static int user_save_internal(User *u) {
113 _cleanup_free_ char *temp_path = NULL;
114 _cleanup_fclose_ FILE *f = NULL;
118 assert(u->state_file);
120 r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
124 r = fopen_temporary(u->state_file, &f, &temp_path);
128 fchmod(fileno(f), 0644);
131 "# This is private data. Do not parse.\n"
135 user_state_to_string(user_get_state(u)));
138 fprintf(f, "RUNTIME=%s\n", u->runtime_path);
141 fprintf(f, "SERVICE=%s\n", u->service);
142 /// elogind does not support service jobs
145 fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
149 fprintf(f, "SLICE=%s\n", u->slice);
150 /// elogind does not support slice jobs
153 fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
157 fprintf(f, "DISPLAY=%s\n", u->display->id);
159 if (dual_timestamp_is_set(&u->timestamp))
161 "REALTIME="USEC_FMT"\n"
162 "MONOTONIC="USEC_FMT"\n",
163 u->timestamp.realtime,
164 u->timestamp.monotonic);
170 fputs("SESSIONS=", f);
172 LIST_FOREACH(sessions_by_user, i, u->sessions) {
181 fputs("\nSEATS=", f);
183 LIST_FOREACH(sessions_by_user, i, u->sessions) {
192 fputs(i->seat->id, f);
195 fputs("\nACTIVE_SESSIONS=", f);
197 LIST_FOREACH(sessions_by_user, i, u->sessions) {
198 if (!session_is_active(i))
209 fputs("\nONLINE_SESSIONS=", f);
211 LIST_FOREACH(sessions_by_user, i, u->sessions) {
212 if (session_get_state(i) == SESSION_CLOSING)
223 fputs("\nACTIVE_SEATS=", f);
225 LIST_FOREACH(sessions_by_user, i, u->sessions) {
226 if (!session_is_active(i) || !i->seat)
234 fputs(i->seat->id, f);
237 fputs("\nONLINE_SEATS=", f);
239 LIST_FOREACH(sessions_by_user, i, u->sessions) {
240 if (session_get_state(i) == SESSION_CLOSING || !i->seat)
248 fputs(i->seat->id, f);
253 r = fflush_and_check(f);
257 if (rename(temp_path, u->state_file) < 0) {
265 (void) unlink(u->state_file);
268 (void) unlink(temp_path);
270 return log_error_errno(r, "Failed to save user data %s: %m", u->state_file);
273 int user_save(User *u) {
279 return user_save_internal (u);
282 int user_load(User *u) {
283 _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
289 r = parse_env_file(u->state_file, NEWLINE,
290 "RUNTIME", &u->runtime_path,
291 "SERVICE", &u->service,
292 /// elogind does not support service jobs
294 "SERVICE_JOB", &u->service_job,
297 /// elogind does not support slice jobs
299 "SLICE_JOB", &u->slice_job,
302 "REALTIME", &realtime,
303 "MONOTONIC", &monotonic,
309 log_error_errno(r, "Failed to read %s: %m", u->state_file);
314 s = hashmap_get(u->manager->sessions, display);
316 if (s && s->display && display_is_local(s->display))
320 unsigned long long l;
321 if (sscanf(realtime, "%llu", &l) > 0)
322 u->timestamp.realtime = l;
326 unsigned long long l;
327 if (sscanf(monotonic, "%llu", &l) > 0)
328 u->timestamp.monotonic = l;
334 static int user_mkdir_runtime_path(User *u) {
340 r = mkdir_safe_label("/run/user", 0755, 0, 0);
342 return log_error_errno(r, "Failed to create /run/user: %m");
344 if (!u->runtime_path) {
345 if (asprintf(&p, "/run/user/" UID_FMT, u->uid) < 0)
350 if (path_is_mount_point(p, 0) <= 0) {
351 _cleanup_free_ char *t = NULL;
353 (void) mkdir_label(p, 0700);
356 r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
358 r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
364 r = mount("tmpfs", p, "tmpfs", MS_NODEV|MS_NOSUID, t);
366 if (errno != EPERM) {
367 r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", p);
371 /* Lacking permissions, maybe
372 * CAP_SYS_ADMIN-less container? In this case,
373 * just use a normal directory. */
375 r = chmod_and_chown(p, 0700, u->uid, u->gid);
377 log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
382 r = label_fix(p, false, false);
384 log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", p);
392 /* Try to clean up, but ignore errors */
397 u->runtime_path = NULL;
401 static int user_start_slice(User *u) {
408 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
409 char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice;
410 sprintf(lu, UID_FMT, u->uid);
412 r = slice_build_subslice("user.slice", lu, &slice);
416 /// elogind : Do not try to use dbus to ask systemd
418 r = manager_start_unit(u->manager, slice, &error, &job);
420 log_error("Failed to start user slice: %s", bus_error_message(&error, r));
426 /// elogind does not support slice jobs
435 hashmap_put(u->manager->user_units, u->slice, u);
440 static int user_start_service(User *u) {
441 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
448 char lu[DECIMAL_STR_MAX(uid_t) + 1], *service;
449 sprintf(lu, UID_FMT, u->uid);
451 r = unit_name_build("user", lu, ".service", &service);
453 return log_error_errno(r, "Failed to build service name: %m");
455 /// elogind : Do not try to use dbus to ask systemd
457 r = manager_start_unit(u->manager, service, &error, &job);
460 log_error("Failed to start user service: %s", bus_error_message(&error, r));
463 u->service = service;
465 /// elogind does not support service jobs
467 free(u->service_job);
468 u->service_job = job;
474 hashmap_put(u->manager->user_units, u->service, u);
479 int user_start(User *u) {
484 if (u->started && !u->stopping)
488 * If u->stopping is set, the user is marked for removal and the slice
489 * and service stop-jobs are queued. We have to clear that flag before
490 * queing the start-jobs again. If they succeed, the user object can be
491 * re-used just fine (pid1 takes care of job-ordering and proper
492 * restart), but if they fail, we want to force another user_stop() so
493 * possibly pending units are stopped.
494 * Note that we don't clear u->started, as we have no clue what state
495 * the user is in on failure here. Hence, we pretend the user is
496 * running so it will be properly taken down by GC. However, we clearly
497 * return an error from user_start() in that case, so no further
498 * reference to the user is taken.
503 log_debug("New user %s logged in.", u->name);
505 /* Make XDG_RUNTIME_DIR */
506 r = user_mkdir_runtime_path(u);
512 r = user_start_slice(u);
516 /* Save the user data so far, because pam_systemd will read the
517 * XDG_RUNTIME_DIR out of it while starting up systemd --user.
518 * We need to do user_save_internal() because we have not
519 * "officially" started yet. */
520 user_save_internal(u);
522 /* Spawn user systemd */
523 r = user_start_service(u);
528 if (!dual_timestamp_is_set(&u->timestamp))
529 dual_timestamp_get(&u->timestamp);
530 user_send_signal(u, true);
534 /* Save new user data */
540 /// UNNEEDED by elogind
542 static int user_stop_slice(User *u) {
543 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
552 r = manager_stop_unit(u->manager, u->slice, &error, &job);
554 log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
564 static int user_stop_service(User *u) {
565 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
574 r = manager_stop_unit(u->manager, u->service, &error, &job);
576 log_error("Failed to stop user service: %s", bus_error_message(&error, r));
580 free(u->service_job);
581 u->service_job = job;
587 static int user_remove_runtime_path(User *u) {
592 if (!u->runtime_path)
595 r = rm_rf(u->runtime_path, 0);
597 log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
599 /* Ignore cases where the directory isn't mounted, as that's
600 * quite possible, if we lacked the permissions to mount
602 r = umount2(u->runtime_path, MNT_DETACH);
603 if (r < 0 && errno != EINVAL && errno != ENOENT)
604 log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
606 r = rm_rf(u->runtime_path, REMOVE_ROOT);
608 log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
610 u->runtime_path = mfree(u->runtime_path);
615 int user_stop(User *u, bool force) {
620 /* Stop jobs have already been queued */
626 LIST_FOREACH(sessions_by_user, s, u->sessions) {
627 k = session_stop(s, force);
633 /// elogind does not support service or slice jobs
635 k = user_stop_service(u);
640 k = user_stop_slice(u);
652 int user_finalize(User *u) {
659 log_debug("User %s logged out.", u->name);
661 LIST_FOREACH(sessions_by_user, s, u->sessions) {
662 k = session_finalize(s);
667 /* Kill XDG_RUNTIME_DIR */
668 k = user_remove_runtime_path(u);
672 /* Clean SysV + POSIX IPC objects */
673 if (u->manager->remove_ipc) {
674 k = clean_ipc(u->uid);
679 unlink(u->state_file);
680 user_add_to_gc_queue(u);
683 user_send_signal(u, false);
690 int user_get_idle_hint(User *u, dual_timestamp *t) {
692 bool idle_hint = true;
693 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
697 LIST_FOREACH(sessions_by_user, s, u->sessions) {
701 ih = session_get_idle_hint(s, &k);
707 if (k.monotonic < ts.monotonic)
713 } else if (idle_hint) {
715 if (k.monotonic > ts.monotonic)
726 int user_check_linger_file(User *u) {
727 _cleanup_free_ char *cc = NULL;
730 cc = cescape(u->name);
734 p = strjoina("/var/lib/systemd/linger/", cc);
736 return access(p, F_OK) >= 0;
739 bool user_check_gc(User *u, bool drop_not_started) {
742 if (drop_not_started && !u->started)
748 if (user_check_linger_file(u) > 0)
751 /// elogind does not support systemd services and slices
753 if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
756 if (u->service_job && manager_job_is_active(u->manager, u->service_job))
763 void user_add_to_gc_queue(User *u) {
769 LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u);
770 u->in_gc_queue = true;
773 UserState user_get_state(User *u) {
781 /// elogind does not support slice and service jobs
783 if (!u->started || u->slice_job || u->service_job)
790 bool all_closing = true;
792 LIST_FOREACH(sessions_by_user, i, u->sessions) {
795 state = session_get_state(i);
796 if (state == SESSION_ACTIVE)
798 if (state != SESSION_CLOSING)
802 return all_closing ? USER_CLOSING : USER_ONLINE;
805 if (user_check_linger_file(u) > 0)
806 return USER_LINGERING;
811 int user_kill(User *u, int signo) {
812 /// Without systemd unit support, elogind has to rely on its session system
819 return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
826 LIST_FOREACH(sessions_by_user, s, u->sessions) {
827 int r = session_kill(s, KILL_ALL, signo);
828 if (res == 0 && r < 0)
836 static bool elect_display_filter(Session *s) {
837 /* Return true if the session is a candidate for the user’s ‘primary
838 * session’ or ‘display’. */
841 return (s->class == SESSION_USER && !s->stopping);
844 static int elect_display_compare(Session *s1, Session *s2) {
845 /* Indexed by SessionType. Lower numbers mean more preferred. */
846 const int type_ranks[_SESSION_TYPE_MAX] = {
847 [SESSION_UNSPECIFIED] = 0,
850 [SESSION_WAYLAND] = -3,
855 /* Calculate the partial order relationship between s1 and s2,
856 * returning < 0 if s1 is preferred as the user’s ‘primary session’,
857 * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
860 * s1 or s2 may be NULL. */
864 if ((s1 == NULL) != (s2 == NULL))
865 return (s1 == NULL) - (s2 == NULL);
867 if (s1->stopping != s2->stopping)
868 return s1->stopping - s2->stopping;
870 if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
871 return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
873 if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
874 return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
876 if (s1->type != s2->type)
877 return type_ranks[s1->type] - type_ranks[s2->type];
882 void user_elect_display(User *u) {
887 /* This elects a primary session for each user, which we call
888 * the "display". We try to keep the assignment stable, but we
889 * "upgrade" to better choices. */
890 log_debug("Electing new display for user %s", u->name);
892 LIST_FOREACH(sessions_by_user, s, u->sessions) {
893 if (!elect_display_filter(s)) {
894 log_debug("Ignoring session %s", s->id);
898 if (elect_display_compare(s, u->display) < 0) {
899 log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
905 static const char* const user_state_table[_USER_STATE_MAX] = {
906 [USER_OFFLINE] = "offline",
907 [USER_OPENING] = "opening",
908 [USER_LINGERING] = "lingering",
909 [USER_ONLINE] = "online",
910 [USER_ACTIVE] = "active",
911 [USER_CLOSING] = "closing"
914 DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
916 int config_parse_tmpfs_size(
918 const char *filename,
921 unsigned section_line,
937 e = endswith(rvalue, "%");
943 ul = strtoul(rvalue, &f, 10);
944 if (errno != 0 || f != e) {
945 log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse percentage value, ignoring: %s", rvalue);
949 if (ul <= 0 || ul >= 100) {
950 log_syntax(unit, LOG_ERR, filename, line, 0, "Percentage value out of range, ignoring: %s", rvalue);
954 *sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100));
958 r = parse_size(rvalue, 1024, &k);
959 if (r < 0 || (uint64_t) (size_t) k != k) {
960 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
964 *sz = PAGE_ALIGN((size_t) k);