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);
464 r = user_start_slice(u);
468 /* Save the user data so far, because pam_systemd will read the
469 * XDG_RUNTIME_DIR out of it while starting up systemd --user.
470 * We need to do user_save_internal() because we have not
471 * "officially" started yet. */
472 user_save_internal(u);
474 /* Spawn user systemd */
475 r = user_start_service(u);
480 if (!dual_timestamp_is_set(&u->timestamp))
481 dual_timestamp_get(&u->timestamp);
485 /* Save new user data */
488 user_send_signal(u, true);
493 static int user_stop_slice(User *u) {
494 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
503 r = manager_stop_unit(u->manager, u->slice, &error, &job);
505 log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
515 static int user_stop_service(User *u) {
516 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
525 r = manager_stop_unit(u->manager, u->service, &error, &job);
527 log_error("Failed to stop user service: %s", bus_error_message(&error, r));
531 free(u->service_job);
532 u->service_job = job;
537 static int user_remove_runtime_path(User *u) {
542 if (!u->runtime_path)
545 r = rm_rf(u->runtime_path, 0);
547 log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
549 /* Ignore cases where the directory isn't mounted, as that's
550 * quite possible, if we lacked the permissions to mount
552 r = umount2(u->runtime_path, MNT_DETACH);
553 if (r < 0 && errno != EINVAL && errno != ENOENT)
554 log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
556 r = rm_rf(u->runtime_path, REMOVE_ROOT);
558 log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
560 free(u->runtime_path);
561 u->runtime_path = NULL;
566 int user_stop(User *u, bool force) {
571 /* Stop jobs have already been queued */
577 LIST_FOREACH(sessions_by_user, s, u->sessions) {
578 k = session_stop(s, force);
584 k = user_stop_service(u);
589 k = user_stop_slice(u);
600 int user_finalize(User *u) {
607 log_debug("User %s logged out.", u->name);
609 LIST_FOREACH(sessions_by_user, s, u->sessions) {
610 k = session_finalize(s);
615 /* Kill XDG_RUNTIME_DIR */
616 k = user_remove_runtime_path(u);
620 /* Clean SysV + POSIX IPC objects */
621 if (u->manager->remove_ipc) {
622 k = clean_ipc(u->uid);
627 unlink(u->state_file);
628 user_add_to_gc_queue(u);
631 user_send_signal(u, false);
638 int user_get_idle_hint(User *u, dual_timestamp *t) {
640 bool idle_hint = true;
641 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
645 LIST_FOREACH(sessions_by_user, s, u->sessions) {
649 ih = session_get_idle_hint(s, &k);
655 if (k.monotonic < ts.monotonic)
661 } else if (idle_hint) {
663 if (k.monotonic > ts.monotonic)
674 int user_check_linger_file(User *u) {
675 _cleanup_free_ char *cc = NULL;
678 cc = cescape(u->name);
682 p = strjoina("/var/lib/systemd/linger/", cc);
684 return access(p, F_OK) >= 0;
687 bool user_check_gc(User *u, bool drop_not_started) {
690 if (drop_not_started && !u->started)
696 if (user_check_linger_file(u) > 0)
699 if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
702 if (u->service_job && manager_job_is_active(u->manager, u->service_job))
708 void user_add_to_gc_queue(User *u) {
714 LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u);
715 u->in_gc_queue = true;
718 UserState user_get_state(User *u) {
726 if (!u->started || u->slice_job || u->service_job)
730 bool all_closing = true;
732 LIST_FOREACH(sessions_by_user, i, u->sessions) {
735 state = session_get_state(i);
736 if (state == SESSION_ACTIVE)
738 if (state != SESSION_CLOSING)
742 return all_closing ? USER_CLOSING : USER_ONLINE;
745 if (user_check_linger_file(u) > 0)
746 return USER_LINGERING;
751 int user_kill(User *u, int signo) {
757 return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
760 static bool elect_display_filter(Session *s) {
761 /* Return true if the session is a candidate for the user’s ‘primary
762 * session’ or ‘display’. */
765 return (s->class == SESSION_USER && !s->stopping);
768 static int elect_display_compare(Session *s1, Session *s2) {
769 /* Indexed by SessionType. Lower numbers mean more preferred. */
770 const int type_ranks[_SESSION_TYPE_MAX] = {
771 [SESSION_UNSPECIFIED] = 0,
774 [SESSION_WAYLAND] = -3,
779 /* Calculate the partial order relationship between s1 and s2,
780 * returning < 0 if s1 is preferred as the user’s ‘primary session’,
781 * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
784 * s1 or s2 may be NULL. */
788 if ((s1 == NULL) != (s2 == NULL))
789 return (s1 == NULL) - (s2 == NULL);
791 if (s1->stopping != s2->stopping)
792 return s1->stopping - s2->stopping;
794 if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
795 return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
797 if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
798 return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
800 if (s1->type != s2->type)
801 return type_ranks[s1->type] - type_ranks[s2->type];
806 void user_elect_display(User *u) {
811 /* This elects a primary session for each user, which we call
812 * the "display". We try to keep the assignment stable, but we
813 * "upgrade" to better choices. */
814 log_debug("Electing new display for user %s", u->name);
816 LIST_FOREACH(sessions_by_user, s, u->sessions) {
817 if (!elect_display_filter(s)) {
818 log_debug("Ignoring session %s", s->id);
822 if (elect_display_compare(s, u->display) < 0) {
823 log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
829 static const char* const user_state_table[_USER_STATE_MAX] = {
830 [USER_OFFLINE] = "offline",
831 [USER_OPENING] = "opening",
832 [USER_LINGERING] = "lingering",
833 [USER_ONLINE] = "online",
834 [USER_ACTIVE] = "active",
835 [USER_CLOSING] = "closing"
838 DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
840 int config_parse_tmpfs_size(
842 const char *filename,
845 unsigned section_line,
861 e = endswith(rvalue, "%");
867 ul = strtoul(rvalue, &f, 10);
868 if (errno != 0 || f != e) {
869 log_syntax(unit, LOG_ERR, filename, line, errno ? errno : EINVAL, "Failed to parse percentage value, ignoring: %s", rvalue);
873 if (ul <= 0 || ul >= 100) {
874 log_syntax(unit, LOG_ERR, filename, line, errno ? errno : EINVAL, "Percentage value out of range, ignoring: %s", rvalue);
878 *sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100));
882 r = parse_size(rvalue, 1024, &o);
883 if (r < 0 || (off_t) (size_t) o != o) {
884 log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue);
888 *sz = PAGE_ALIGN((size_t) o);