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"
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);
100 free(u->runtime_path);
102 hashmap_remove(u->manager->users, UID_TO_PTR(u->uid));
109 static int user_save_internal(User *u) {
110 _cleanup_free_ char *temp_path = NULL;
111 _cleanup_fclose_ FILE *f = NULL;
115 assert(u->state_file);
117 r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
121 r = fopen_temporary(u->state_file, &f, &temp_path);
125 fchmod(fileno(f), 0644);
128 "# This is private data. Do not parse.\n"
132 user_state_to_string(user_get_state(u)));
135 fprintf(f, "RUNTIME=%s\n", u->runtime_path);
138 fprintf(f, "SERVICE=%s\n", u->service);
140 fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
143 fprintf(f, "SLICE=%s\n", u->slice);
145 fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
148 fprintf(f, "DISPLAY=%s\n", u->display->id);
150 if (dual_timestamp_is_set(&u->timestamp))
152 "REALTIME="USEC_FMT"\n"
153 "MONOTONIC="USEC_FMT"\n",
154 u->timestamp.realtime,
155 u->timestamp.monotonic);
161 fputs("SESSIONS=", f);
163 LIST_FOREACH(sessions_by_user, i, u->sessions) {
172 fputs("\nSEATS=", f);
174 LIST_FOREACH(sessions_by_user, i, u->sessions) {
183 fputs(i->seat->id, f);
186 fputs("\nACTIVE_SESSIONS=", f);
188 LIST_FOREACH(sessions_by_user, i, u->sessions) {
189 if (!session_is_active(i))
200 fputs("\nONLINE_SESSIONS=", f);
202 LIST_FOREACH(sessions_by_user, i, u->sessions) {
203 if (session_get_state(i) == SESSION_CLOSING)
214 fputs("\nACTIVE_SEATS=", f);
216 LIST_FOREACH(sessions_by_user, i, u->sessions) {
217 if (!session_is_active(i) || !i->seat)
225 fputs(i->seat->id, f);
228 fputs("\nONLINE_SEATS=", f);
230 LIST_FOREACH(sessions_by_user, i, u->sessions) {
231 if (session_get_state(i) == SESSION_CLOSING || !i->seat)
239 fputs(i->seat->id, f);
246 if (ferror(f) || rename(temp_path, u->state_file) < 0) {
248 unlink(u->state_file);
254 log_error_errno(r, "Failed to save user data %s: %m", u->state_file);
259 int user_save(User *u) {
265 return user_save_internal (u);
268 int user_load(User *u) {
269 _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
275 r = parse_env_file(u->state_file, NEWLINE,
276 "RUNTIME", &u->runtime_path,
277 "SERVICE", &u->service,
278 "SERVICE_JOB", &u->service_job,
280 "SLICE_JOB", &u->slice_job,
282 "REALTIME", &realtime,
283 "MONOTONIC", &monotonic,
289 log_error_errno(r, "Failed to read %s: %m", u->state_file);
294 s = hashmap_get(u->manager->sessions, display);
296 if (s && s->display && display_is_local(s->display))
300 unsigned long long l;
301 if (sscanf(realtime, "%llu", &l) > 0)
302 u->timestamp.realtime = l;
306 unsigned long long l;
307 if (sscanf(monotonic, "%llu", &l) > 0)
308 u->timestamp.monotonic = l;
314 static int user_mkdir_runtime_path(User *u) {
320 r = mkdir_safe_label("/run/user", 0755, 0, 0);
322 return log_error_errno(r, "Failed to create /run/user: %m");
324 if (!u->runtime_path) {
325 if (asprintf(&p, "/run/user/" UID_FMT, u->uid) < 0)
330 if (path_is_mount_point(p, 0) <= 0) {
331 _cleanup_free_ char *t = NULL;
333 (void) mkdir_label(p, 0700);
336 r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
338 r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
344 r = mount("tmpfs", p, "tmpfs", MS_NODEV|MS_NOSUID, t);
346 if (errno != EPERM) {
347 r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", p);
351 /* Lacking permissions, maybe
352 * CAP_SYS_ADMIN-less container? In this case,
353 * just use a normal directory. */
355 r = chmod_and_chown(p, 0700, u->uid, u->gid);
357 log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
362 r = label_fix(p, false, false);
364 log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", p);
372 /* Try to clean up, but ignore errors */
377 u->runtime_path = NULL;
381 static int user_start_slice(User *u) {
388 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
389 char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice;
390 sprintf(lu, UID_FMT, u->uid);
392 r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &slice);
396 r = manager_start_unit(u->manager, slice, &error, &job);
398 log_error("Failed to start user slice: %s", bus_error_message(&error, r));
409 hashmap_put(u->manager->user_units, u->slice, u);
414 static int user_start_service(User *u) {
415 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
422 char lu[DECIMAL_STR_MAX(uid_t) + 1], *service;
423 sprintf(lu, UID_FMT, u->uid);
425 r = unit_name_build("user", lu, ".service", &service);
427 return log_error_errno(r, "Failed to build service name: %m");
429 r = manager_start_unit(u->manager, service, &error, &job);
431 log_error("Failed to start user service: %s", bus_error_message(&error, r));
434 u->service = service;
436 free(u->service_job);
437 u->service_job = job;
442 hashmap_put(u->manager->user_units, u->service, u);
447 int user_start(User *u) {
455 log_debug("New user %s logged in.", u->name);
457 /* Make XDG_RUNTIME_DIR */
458 r = user_mkdir_runtime_path(u);
463 r = user_start_slice(u);
467 /* Save the user data so far, because pam_systemd will read the
468 * XDG_RUNTIME_DIR out of it while starting up systemd --user.
469 * We need to do user_save_internal() because we have not
470 * "officially" started yet. */
471 user_save_internal(u);
473 /* Spawn user systemd */
474 r = user_start_service(u);
478 if (!dual_timestamp_is_set(&u->timestamp))
479 dual_timestamp_get(&u->timestamp);
483 /* Save new user data */
486 user_send_signal(u, true);
491 static int user_stop_slice(User *u) {
492 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
501 r = manager_stop_unit(u->manager, u->slice, &error, &job);
503 log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
513 static int user_stop_service(User *u) {
514 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
523 r = manager_stop_unit(u->manager, u->service, &error, &job);
525 log_error("Failed to stop user service: %s", bus_error_message(&error, r));
529 free(u->service_job);
530 u->service_job = job;
535 static int user_remove_runtime_path(User *u) {
540 if (!u->runtime_path)
543 r = rm_rf(u->runtime_path, 0);
545 log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
547 /* Ignore cases where the directory isn't mounted, as that's
548 * quite possible, if we lacked the permissions to mount
550 r = umount2(u->runtime_path, MNT_DETACH);
551 if (r < 0 && errno != EINVAL && errno != ENOENT)
552 log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
554 r = rm_rf(u->runtime_path, REMOVE_ROOT);
556 log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
558 free(u->runtime_path);
559 u->runtime_path = NULL;
564 int user_stop(User *u, bool force) {
569 /* Stop jobs have already been queued */
575 LIST_FOREACH(sessions_by_user, s, u->sessions) {
576 k = session_stop(s, force);
582 k = user_stop_service(u);
587 k = user_stop_slice(u);
598 int user_finalize(User *u) {
605 log_debug("User %s logged out.", u->name);
607 LIST_FOREACH(sessions_by_user, s, u->sessions) {
608 k = session_finalize(s);
613 /* Kill XDG_RUNTIME_DIR */
614 k = user_remove_runtime_path(u);
618 /* Clean SysV + POSIX IPC objects */
619 if (u->manager->remove_ipc) {
620 k = clean_ipc(u->uid);
625 unlink(u->state_file);
626 user_add_to_gc_queue(u);
629 user_send_signal(u, false);
636 int user_get_idle_hint(User *u, dual_timestamp *t) {
638 bool idle_hint = true;
639 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
643 LIST_FOREACH(sessions_by_user, s, u->sessions) {
647 ih = session_get_idle_hint(s, &k);
653 if (k.monotonic < ts.monotonic)
659 } else if (idle_hint) {
661 if (k.monotonic > ts.monotonic)
672 int user_check_linger_file(User *u) {
673 _cleanup_free_ char *cc = NULL;
676 cc = cescape(u->name);
680 p = strjoina("/var/lib/systemd/linger/", cc);
682 return access(p, F_OK) >= 0;
685 bool user_check_gc(User *u, bool drop_not_started) {
688 if (drop_not_started && !u->started)
694 if (user_check_linger_file(u) > 0)
697 if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
700 if (u->service_job && manager_job_is_active(u->manager, u->service_job))
706 void user_add_to_gc_queue(User *u) {
712 LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u);
713 u->in_gc_queue = true;
716 UserState user_get_state(User *u) {
724 if (!u->started || u->slice_job || u->service_job)
728 bool all_closing = true;
730 LIST_FOREACH(sessions_by_user, i, u->sessions) {
733 state = session_get_state(i);
734 if (state == SESSION_ACTIVE)
736 if (state != SESSION_CLOSING)
740 return all_closing ? USER_CLOSING : USER_ONLINE;
743 if (user_check_linger_file(u) > 0)
744 return USER_LINGERING;
749 int user_kill(User *u, int signo) {
755 return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
758 static bool elect_display_filter(Session *s) {
759 /* Return true if the session is a candidate for the user’s ‘primary
760 * session’ or ‘display’. */
763 return (s->class == SESSION_USER && !s->stopping);
766 static int elect_display_compare(Session *s1, Session *s2) {
767 /* Indexed by SessionType. Lower numbers mean more preferred. */
768 const int type_ranks[_SESSION_TYPE_MAX] = {
769 [SESSION_UNSPECIFIED] = 0,
772 [SESSION_WAYLAND] = -3,
777 /* Calculate the partial order relationship between s1 and s2,
778 * returning < 0 if s1 is preferred as the user’s ‘primary session’,
779 * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
782 * s1 or s2 may be NULL. */
786 if ((s1 == NULL) != (s2 == NULL))
787 return (s1 == NULL) - (s2 == NULL);
789 if (s1->stopping != s2->stopping)
790 return s1->stopping - s2->stopping;
792 if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
793 return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
795 if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
796 return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
798 if (s1->type != s2->type)
799 return type_ranks[s1->type] - type_ranks[s2->type];
804 void user_elect_display(User *u) {
809 /* This elects a primary session for each user, which we call
810 * the "display". We try to keep the assignment stable, but we
811 * "upgrade" to better choices. */
812 log_debug("Electing new display for user %s", u->name);
814 LIST_FOREACH(sessions_by_user, s, u->sessions) {
815 if (!elect_display_filter(s)) {
816 log_debug("Ignoring session %s", s->id);
820 if (elect_display_compare(s, u->display) < 0) {
821 log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
827 static const char* const user_state_table[_USER_STATE_MAX] = {
828 [USER_OFFLINE] = "offline",
829 [USER_OPENING] = "opening",
830 [USER_LINGERING] = "lingering",
831 [USER_ONLINE] = "online",
832 [USER_ACTIVE] = "active",
833 [USER_CLOSING] = "closing"
836 DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
838 int config_parse_tmpfs_size(
840 const char *filename,
843 unsigned section_line,
859 e = endswith(rvalue, "%");
865 ul = strtoul(rvalue, &f, 10);
866 if (errno != 0 || f != e) {
867 log_syntax(unit, LOG_ERR, filename, line, errno ? errno : EINVAL, "Failed to parse percentage value, ignoring: %s", rvalue);
871 if (ul <= 0 || ul >= 100) {
872 log_syntax(unit, LOG_ERR, filename, line, errno ? errno : EINVAL, "Percentage value out of range, ignoring: %s", rvalue);
876 *sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100));
880 r = parse_size(rvalue, 1024, &o);
881 if (r < 0 || (off_t) (size_t) o != o) {
882 log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue);
886 *sz = PAGE_ALIGN((size_t) o);