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/>.
24 #include <sys/mount.h>
27 #include "alloc-util.h"
28 #include "bus-common-errors.h"
29 #include "bus-error.h"
31 #include "clean-ipc.h"
32 #include "conf-parser.h"
36 #include "formats-util.h"
40 #include "logind-user.h"
42 #include "mount-util.h"
43 #include "parse-util.h"
44 #include "path-util.h"
46 #include "smack-util.h"
47 //#include "special.h"
48 #include "stdio-util.h"
49 #include "string-table.h"
50 #include "unit-name.h"
51 #include "user-util.h"
54 int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
55 _cleanup_(user_freep) User *u = NULL;
56 char lu[DECIMAL_STR_MAX(uid_t) + 1];
70 xsprintf(lu, UID_FMT, uid);
72 u->name = strdup(name);
76 if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
79 if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0)
82 r = slice_build_subslice("user.slice", lu, &u->slice);
86 r = unit_name_build("user", lu, ".service", &u->service);
90 r = hashmap_put(m->users, UID_TO_PTR(uid), u);
94 r = hashmap_put(m->user_units, u->slice, u);
98 r = hashmap_put(m->user_units, u->service, u);
107 User *user_free(User *u) {
112 LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u);
115 session_free(u->sessions);
118 hashmap_remove_value(u->manager->user_units, u->service, u);
121 hashmap_remove_value(u->manager->user_units, u->slice, u);
123 hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u);
125 /// elogind neither supports slice nor service jobs.
127 u->slice_job = mfree(u->slice_job);
128 u->service_job = mfree(u->service_job);
130 u->service = mfree(u->service);
131 u->slice = mfree(u->slice);
132 u->runtime_path = mfree(u->runtime_path);
133 u->state_file = mfree(u->state_file);
134 u->name = mfree(u->name);
139 static int user_save_internal(User *u) {
140 _cleanup_free_ char *temp_path = NULL;
141 _cleanup_fclose_ FILE *f = NULL;
145 assert(u->state_file);
147 r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
151 r = fopen_temporary(u->state_file, &f, &temp_path);
155 fchmod(fileno(f), 0644);
158 "# This is private data. Do not parse.\n"
162 user_state_to_string(user_get_state(u)));
164 /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */
166 fprintf(f, "RUNTIME=%s\n", u->runtime_path);
168 /// elogind neither supports service nor slice jobs
171 fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
174 fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
178 fprintf(f, "DISPLAY=%s\n", u->display->id);
180 if (dual_timestamp_is_set(&u->timestamp))
182 "REALTIME="USEC_FMT"\n"
183 "MONOTONIC="USEC_FMT"\n",
184 u->timestamp.realtime,
185 u->timestamp.monotonic);
191 fputs("SESSIONS=", f);
193 LIST_FOREACH(sessions_by_user, i, u->sessions) {
202 fputs("\nSEATS=", f);
204 LIST_FOREACH(sessions_by_user, i, u->sessions) {
213 fputs(i->seat->id, f);
216 fputs("\nACTIVE_SESSIONS=", f);
218 LIST_FOREACH(sessions_by_user, i, u->sessions) {
219 if (!session_is_active(i))
230 fputs("\nONLINE_SESSIONS=", f);
232 LIST_FOREACH(sessions_by_user, i, u->sessions) {
233 if (session_get_state(i) == SESSION_CLOSING)
244 fputs("\nACTIVE_SEATS=", f);
246 LIST_FOREACH(sessions_by_user, i, u->sessions) {
247 if (!session_is_active(i) || !i->seat)
255 fputs(i->seat->id, f);
258 fputs("\nONLINE_SEATS=", f);
260 LIST_FOREACH(sessions_by_user, i, u->sessions) {
261 if (session_get_state(i) == SESSION_CLOSING || !i->seat)
269 fputs(i->seat->id, f);
274 r = fflush_and_check(f);
278 if (rename(temp_path, u->state_file) < 0) {
286 (void) unlink(u->state_file);
289 (void) unlink(temp_path);
291 return log_error_errno(r, "Failed to save user data %s: %m", u->state_file);
294 int user_save(User *u) {
300 return user_save_internal (u);
303 int user_load(User *u) {
304 _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
310 r = parse_env_file(u->state_file, NEWLINE,
311 /// 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 log_error_errno(r, "Failed to read %s: %m", u->state_file);
329 s = hashmap_get(u->manager->sessions, display);
331 if (s && s->display && display_is_local(s->display))
335 unsigned long long l;
336 if (sscanf(realtime, "%llu", &l) > 0)
337 u->timestamp.realtime = l;
341 unsigned long long l;
342 if (sscanf(monotonic, "%llu", &l) > 0)
343 u->timestamp.monotonic = l;
349 static int user_mkdir_runtime_path(User *u) {
354 r = mkdir_safe_label("/run/user", 0755, 0, 0);
356 return log_error_errno(r, "Failed to create /run/user: %m");
358 if (path_is_mount_point(u->runtime_path, 0) <= 0) {
359 _cleanup_free_ char *t = NULL;
361 (void) mkdir_label(u->runtime_path, 0700);
364 r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
366 r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
372 r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t);
374 if (errno != EPERM) {
375 r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path);
379 /* Lacking permissions, maybe
380 * CAP_SYS_ADMIN-less container? In this case,
381 * just use a normal directory. */
383 r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid);
385 log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
390 r = label_fix(u->runtime_path, false, false);
392 log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", u->runtime_path);
398 /* Try to clean up, but ignore errors */
399 (void) rmdir(u->runtime_path);
403 static int user_start_slice(User *u) {
404 /// elogind can not ask systemd via dbus to start user services
406 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
407 const char *description;
413 u->slice_job = mfree(u->slice_job);
414 description = strjoina("User Slice of ", u->name);
416 r = manager_start_slice(
420 "systemd-logind.service",
421 "systemd-user-sessions.service",
422 u->manager->user_tasks_max,
426 /* we don't fail due to this, let's try to continue */
427 if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
428 log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)", u->slice, bus_error_message(&error, r), error.name);
435 hashmap_put(u->manager->user_units, u->slice, u);
441 static int user_start_service(User *u) {
442 /// elogind can not ask systemd via dbus to start user services
444 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
450 u->service_job = mfree(u->service_job);
452 r = manager_start_unit(
458 /* we don't fail due to this, let's try to continue */
459 log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r));
461 u->service_job = job;
466 hashmap_put(u->manager->user_units, u->service, u);
472 int user_start(User *u) {
477 if (u->started && !u->stopping)
481 * If u->stopping is set, the user is marked for removal and the slice
482 * and service stop-jobs are queued. We have to clear that flag before
483 * queing the start-jobs again. If they succeed, the user object can be
484 * re-used just fine (pid1 takes care of job-ordering and proper
485 * restart), but if they fail, we want to force another user_stop() so
486 * possibly pending units are stopped.
487 * Note that we don't clear u->started, as we have no clue what state
488 * the user is in on failure here. Hence, we pretend the user is
489 * running so it will be properly taken down by GC. However, we clearly
490 * return an error from user_start() in that case, so no further
491 * reference to the user is taken.
496 log_debug("New user %s logged in.", u->name);
498 /* Make XDG_RUNTIME_DIR */
499 r = user_mkdir_runtime_path(u);
505 r = user_start_slice(u);
509 /* Save the user data so far, because pam_systemd will read the
510 * XDG_RUNTIME_DIR out of it while starting up systemd --user.
511 * We need to do user_save_internal() because we have not
512 * "officially" started yet. */
513 user_save_internal(u);
515 /* Spawn user systemd */
516 r = user_start_service(u);
521 if (!dual_timestamp_is_set(&u->timestamp))
522 dual_timestamp_get(&u->timestamp);
523 user_send_signal(u, true);
527 /* Save new user data */
533 /// UNNEEDED by elogind
535 static int user_stop_slice(User *u) {
536 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
542 r = manager_stop_unit(u->manager, u->slice, &error, &job);
544 log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
554 static int user_stop_service(User *u) {
555 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
561 r = manager_stop_unit(u->manager, u->service, &error, &job);
563 log_error("Failed to stop user service: %s", bus_error_message(&error, r));
567 free(u->service_job);
568 u->service_job = job;
574 static int user_remove_runtime_path(User *u) {
579 r = rm_rf(u->runtime_path, 0);
581 log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
583 /* Ignore cases where the directory isn't mounted, as that's
584 * quite possible, if we lacked the permissions to mount
586 r = umount2(u->runtime_path, MNT_DETACH);
587 if (r < 0 && errno != EINVAL && errno != ENOENT)
588 log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
590 r = rm_rf(u->runtime_path, REMOVE_ROOT);
592 log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
597 int user_stop(User *u, bool force) {
602 /* Stop jobs have already been queued */
608 LIST_FOREACH(sessions_by_user, s, u->sessions) {
609 k = session_stop(s, force);
615 /// elogind does not support service or slice jobs
617 k = user_stop_service(u);
622 k = user_stop_slice(u);
634 int user_finalize(User *u) {
641 log_debug("User %s logged out.", u->name);
643 LIST_FOREACH(sessions_by_user, s, u->sessions) {
644 k = session_finalize(s);
649 /* Kill XDG_RUNTIME_DIR */
650 k = user_remove_runtime_path(u);
654 /* Clean SysV + POSIX IPC objects */
655 if (u->manager->remove_ipc) {
656 k = clean_ipc(u->uid);
661 unlink(u->state_file);
662 user_add_to_gc_queue(u);
665 user_send_signal(u, false);
672 int user_get_idle_hint(User *u, dual_timestamp *t) {
674 bool idle_hint = true;
675 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
679 LIST_FOREACH(sessions_by_user, s, u->sessions) {
683 ih = session_get_idle_hint(s, &k);
689 if (k.monotonic < ts.monotonic)
695 } else if (idle_hint) {
697 if (k.monotonic > ts.monotonic)
708 int user_check_linger_file(User *u) {
709 _cleanup_free_ char *cc = NULL;
712 cc = cescape(u->name);
716 p = strjoina("/var/lib/systemd/linger/", cc);
718 return access(p, F_OK) >= 0;
721 bool user_check_gc(User *u, bool drop_not_started) {
724 if (drop_not_started && !u->started)
730 if (user_check_linger_file(u) > 0)
733 /// elogind neither supports service nor slice jobs
735 if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
738 if (u->service_job && manager_job_is_active(u->manager, u->service_job))
745 void user_add_to_gc_queue(User *u) {
751 LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u);
752 u->in_gc_queue = true;
755 UserState user_get_state(User *u) {
763 /// elogind neither supports service nor slice jobs.
765 if (!u->started || u->slice_job || u->service_job)
772 bool all_closing = true;
774 LIST_FOREACH(sessions_by_user, i, u->sessions) {
777 state = session_get_state(i);
778 if (state == SESSION_ACTIVE)
780 if (state != SESSION_CLOSING)
784 return all_closing ? USER_CLOSING : USER_ONLINE;
787 if (user_check_linger_file(u) > 0)
788 return USER_LINGERING;
793 int user_kill(User *u, int signo) {
794 /// Without systemd unit support, elogind has to rely on its session system
798 return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
805 LIST_FOREACH(sessions_by_user, s, u->sessions) {
806 int r = session_kill(s, KILL_ALL, signo);
807 if (res == 0 && r < 0)
815 static bool elect_display_filter(Session *s) {
816 /* Return true if the session is a candidate for the user’s ‘primary
817 * session’ or ‘display’. */
820 return (s->class == SESSION_USER && !s->stopping);
823 static int elect_display_compare(Session *s1, Session *s2) {
824 /* Indexed by SessionType. Lower numbers mean more preferred. */
825 const int type_ranks[_SESSION_TYPE_MAX] = {
826 [SESSION_UNSPECIFIED] = 0,
829 [SESSION_WAYLAND] = -3,
834 /* Calculate the partial order relationship between s1 and s2,
835 * returning < 0 if s1 is preferred as the user’s ‘primary session’,
836 * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
839 * s1 or s2 may be NULL. */
843 if ((s1 == NULL) != (s2 == NULL))
844 return (s1 == NULL) - (s2 == NULL);
846 if (s1->stopping != s2->stopping)
847 return s1->stopping - s2->stopping;
849 if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
850 return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
852 if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
853 return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
855 if (s1->type != s2->type)
856 return type_ranks[s1->type] - type_ranks[s2->type];
861 void user_elect_display(User *u) {
866 /* This elects a primary session for each user, which we call
867 * the "display". We try to keep the assignment stable, but we
868 * "upgrade" to better choices. */
869 log_debug("Electing new display for user %s", u->name);
871 LIST_FOREACH(sessions_by_user, s, u->sessions) {
872 if (!elect_display_filter(s)) {
873 log_debug("Ignoring session %s", s->id);
877 if (elect_display_compare(s, u->display) < 0) {
878 log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
884 static const char* const user_state_table[_USER_STATE_MAX] = {
885 [USER_OFFLINE] = "offline",
886 [USER_OPENING] = "opening",
887 [USER_LINGERING] = "lingering",
888 [USER_ONLINE] = "online",
889 [USER_ACTIVE] = "active",
890 [USER_CLOSING] = "closing"
893 DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
895 int config_parse_tmpfs_size(
897 const char *filename,
900 unsigned section_line,
916 e = endswith(rvalue, "%");
922 ul = strtoul(rvalue, &f, 10);
923 if (errno != 0 || f != e) {
924 log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse percentage value, ignoring: %s", rvalue);
928 if (ul <= 0 || ul >= 100) {
929 log_syntax(unit, LOG_ERR, filename, line, 0, "Percentage value out of range, ignoring: %s", rvalue);
933 *sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100));
937 r = parse_size(rvalue, 1024, &k);
938 if (r < 0 || (uint64_t) (size_t) k != k) {
939 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
943 *sz = PAGE_ALIGN((size_t) k);