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>
26 #include "alloc-util.h"
27 #include "bus-common-errors.h"
28 #include "bus-error.h"
30 #include "cgroup-util.h"
31 #include "clean-ipc.h"
32 #include "conf-parser.h"
36 #include "format-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"
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(SPECIAL_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 u
->slice_job
= mfree(u
->slice_job
);
126 u
->service_job
= mfree(u
->service_job
);
128 u
->service
= mfree(u
->service
);
129 u
->slice
= mfree(u
->slice
);
130 u
->runtime_path
= mfree(u
->runtime_path
);
131 u
->state_file
= mfree(u
->state_file
);
132 u
->name
= mfree(u
->name
);
137 static int user_save_internal(User
*u
) {
138 _cleanup_free_
char *temp_path
= NULL
;
139 _cleanup_fclose_
FILE *f
= NULL
;
143 assert(u
->state_file
);
145 r
= mkdir_safe_label("/run/systemd/users", 0755, 0, 0, false);
149 r
= fopen_temporary(u
->state_file
, &f
, &temp_path
);
153 fchmod(fileno(f
), 0644);
156 "# This is private data. Do not parse.\n"
160 user_state_to_string(user_get_state(u
)));
162 /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */
164 fprintf(f
, "RUNTIME=%s\n", u
->runtime_path
);
167 fprintf(f
, "SERVICE_JOB=%s\n", u
->service_job
);
170 fprintf(f
, "SLICE_JOB=%s\n", u
->slice_job
);
173 fprintf(f
, "DISPLAY=%s\n", u
->display
->id
);
175 if (dual_timestamp_is_set(&u
->timestamp
))
177 "REALTIME="USEC_FMT
"\n"
178 "MONOTONIC="USEC_FMT
"\n",
179 u
->timestamp
.realtime
,
180 u
->timestamp
.monotonic
);
186 fputs_unlocked("SESSIONS=", f
);
188 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
192 fputc_unlocked(' ', f
);
194 fputs_unlocked(i
->id
, f
);
197 fputs_unlocked("\nSEATS=", f
);
199 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
206 fputc_unlocked(' ', f
);
208 fputs_unlocked(i
->seat
->id
, f
);
211 fputs_unlocked("\nACTIVE_SESSIONS=", f
);
213 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
214 if (!session_is_active(i
))
220 fputc_unlocked(' ', f
);
222 fputs_unlocked(i
->id
, f
);
225 fputs_unlocked("\nONLINE_SESSIONS=", f
);
227 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
228 if (session_get_state(i
) == SESSION_CLOSING
)
234 fputc_unlocked(' ', f
);
236 fputs_unlocked(i
->id
, f
);
239 fputs_unlocked("\nACTIVE_SEATS=", f
);
241 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
242 if (!session_is_active(i
) || !i
->seat
)
248 fputc_unlocked(' ', f
);
250 fputs_unlocked(i
->seat
->id
, f
);
253 fputs_unlocked("\nONLINE_SEATS=", f
);
255 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
256 if (session_get_state(i
) == SESSION_CLOSING
|| !i
->seat
)
262 fputc_unlocked(' ', f
);
264 fputs_unlocked(i
->seat
->id
, f
);
266 fputc_unlocked('\n', f
);
269 r
= fflush_and_check(f
);
273 if (rename(temp_path
, u
->state_file
) < 0) {
281 (void) unlink(u
->state_file
);
284 (void) unlink(temp_path
);
286 return log_error_errno(r
, "Failed to save user data %s: %m", u
->state_file
);
289 int user_save(User
*u
) {
295 return user_save_internal (u
);
298 int user_load(User
*u
) {
299 _cleanup_free_
char *display
= NULL
, *realtime
= NULL
, *monotonic
= NULL
;
305 r
= parse_env_file(u
->state_file
, NEWLINE
,
306 "SERVICE_JOB", &u
->service_job
,
307 "SLICE_JOB", &u
->slice_job
,
309 "REALTIME", &realtime
,
310 "MONOTONIC", &monotonic
,
316 return log_error_errno(r
, "Failed to read %s: %m", u
->state_file
);
320 s
= hashmap_get(u
->manager
->sessions
, display
);
322 if (s
&& s
->display
&& display_is_local(s
->display
))
326 timestamp_deserialize(realtime
, &u
->timestamp
.realtime
);
328 timestamp_deserialize(monotonic
, &u
->timestamp
.monotonic
);
333 static int user_mkdir_runtime_path(User
*u
) {
338 r
= mkdir_safe_label("/run/user", 0755, 0, 0, false);
340 return log_error_errno(r
, "Failed to create /run/user: %m");
342 if (path_is_mount_point(u
->runtime_path
, NULL
, 0) <= 0) {
343 _cleanup_free_
char *t
= NULL
;
345 (void) mkdir_label(u
->runtime_path
, 0700);
348 r
= asprintf(&t
, "mode=0700,smackfsroot=*,uid=" UID_FMT
",gid=" GID_FMT
",size=%zu", u
->uid
, u
->gid
, u
->manager
->runtime_dir_size
);
350 r
= asprintf(&t
, "mode=0700,uid=" UID_FMT
",gid=" GID_FMT
",size=%zu", u
->uid
, u
->gid
, u
->manager
->runtime_dir_size
);
356 r
= mount("tmpfs", u
->runtime_path
, "tmpfs", MS_NODEV
|MS_NOSUID
, t
);
358 if (!IN_SET(errno
, EPERM
, EACCES
)) {
359 r
= log_error_errno(errno
, "Failed to mount per-user tmpfs directory %s: %m", u
->runtime_path
);
363 log_debug_errno(errno
, "Failed to mount per-user tmpfs directory %s, assuming containerized execution, ignoring: %m", u
->runtime_path
);
365 r
= chmod_and_chown(u
->runtime_path
, 0700, u
->uid
, u
->gid
);
367 log_error_errno(r
, "Failed to change runtime directory ownership and mode: %m");
372 r
= label_fix(u
->runtime_path
, false, false);
374 log_warning_errno(r
, "Failed to fix label of '%s', ignoring: %m", u
->runtime_path
);
380 /* Try to clean up, but ignore errors */
381 (void) rmdir(u
->runtime_path
);
385 static int user_start_slice(User
*u
) {
386 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
387 const char *description
;
393 u
->slice_job
= mfree(u
->slice_job
);
394 description
= strjoina("User Slice of ", u
->name
);
396 r
= manager_start_slice(
400 "systemd-logind.service",
401 "systemd-user-sessions.service",
402 u
->manager
->user_tasks_max
,
407 else if (!sd_bus_error_has_name(&error
, BUS_ERROR_UNIT_EXISTS
))
408 /* we don't fail due to this, let's try to continue */
409 log_error_errno(r
, "Failed to start user slice %s, ignoring: %s (%s)",
410 u
->slice
, bus_error_message(&error
, r
), error
.name
);
415 static int user_start_service(User
*u
) {
416 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
422 u
->service_job
= mfree(u
->service_job
);
424 r
= manager_start_unit(
430 /* we don't fail due to this, let's try to continue */
431 log_error_errno(r
, "Failed to start user service, ignoring: %s", bus_error_message(&error
, r
));
433 u
->service_job
= job
;
438 int user_start(User
*u
) {
443 if (u
->started
&& !u
->stopping
)
447 * If u->stopping is set, the user is marked for removal and the slice
448 * and service stop-jobs are queued. We have to clear that flag before
449 * queing the start-jobs again. If they succeed, the user object can be
450 * re-used just fine (pid1 takes care of job-ordering and proper
451 * restart), but if they fail, we want to force another user_stop() so
452 * possibly pending units are stopped.
453 * Note that we don't clear u->started, as we have no clue what state
454 * the user is in on failure here. Hence, we pretend the user is
455 * running so it will be properly taken down by GC. However, we clearly
456 * return an error from user_start() in that case, so no further
457 * reference to the user is taken.
462 log_debug("New user %s logged in.", u
->name
);
464 /* Make XDG_RUNTIME_DIR */
465 r
= user_mkdir_runtime_path(u
);
471 r
= user_start_slice(u
);
475 /* Save the user data so far, because pam_systemd will read the
476 * XDG_RUNTIME_DIR out of it while starting up systemd --user.
477 * We need to do user_save_internal() because we have not
478 * "officially" started yet. */
479 user_save_internal(u
);
481 /* Spawn user systemd */
482 r
= user_start_service(u
);
487 if (!dual_timestamp_is_set(&u
->timestamp
))
488 dual_timestamp_get(&u
->timestamp
);
489 user_send_signal(u
, true);
493 /* Save new user data */
499 static int user_stop_slice(User
*u
) {
500 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
506 r
= manager_stop_unit(u
->manager
, u
->slice
, &error
, &job
);
508 log_error("Failed to stop user slice: %s", bus_error_message(&error
, r
));
518 static int user_stop_service(User
*u
) {
519 _cleanup_(sd_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 r
= rm_rf(u
->runtime_path
, 0);
544 log_error_errno(r
, "Failed to remove runtime directory %s (before unmounting): %m", u
->runtime_path
);
546 /* Ignore cases where the directory isn't mounted, as that's
547 * quite possible, if we lacked the permissions to mount
549 r
= umount2(u
->runtime_path
, MNT_DETACH
);
550 if (r
< 0 && !IN_SET(errno
, EINVAL
, ENOENT
))
551 log_error_errno(errno
, "Failed to unmount user runtime directory %s: %m", u
->runtime_path
);
553 r
= rm_rf(u
->runtime_path
, REMOVE_ROOT
);
555 log_error_errno(r
, "Failed to remove runtime directory %s (after unmounting): %m", u
->runtime_path
);
560 int user_stop(User
*u
, bool force
) {
565 /* Stop jobs have already been queued */
571 LIST_FOREACH(sessions_by_user
, s
, u
->sessions
) {
572 k
= session_stop(s
, force
);
578 k
= user_stop_service(u
);
583 k
= user_stop_slice(u
);
594 int user_finalize(User
*u
) {
601 log_debug("User %s logged out.", u
->name
);
603 LIST_FOREACH(sessions_by_user
, s
, u
->sessions
) {
604 k
= session_finalize(s
);
609 /* Kill XDG_RUNTIME_DIR */
610 k
= user_remove_runtime_path(u
);
614 /* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs
615 * are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to
616 * system components. Since enable RemoveIPC= globally for all users, we need to be a bit careful with such
617 * cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because
618 * a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up,
619 * and do it only for normal users. */
620 if (u
->manager
->remove_ipc
&& u
->uid
> SYSTEM_UID_MAX
) {
621 k
= clean_ipc_by_uid(u
->uid
);
626 unlink(u
->state_file
);
627 user_add_to_gc_queue(u
);
630 user_send_signal(u
, false);
637 int user_get_idle_hint(User
*u
, dual_timestamp
*t
) {
639 bool idle_hint
= true;
640 dual_timestamp ts
= DUAL_TIMESTAMP_NULL
;
644 LIST_FOREACH(sessions_by_user
, s
, u
->sessions
) {
648 ih
= session_get_idle_hint(s
, &k
);
654 if (k
.monotonic
< ts
.monotonic
)
660 } else if (idle_hint
) {
662 if (k
.monotonic
> ts
.monotonic
)
673 int user_check_linger_file(User
*u
) {
674 _cleanup_free_
char *cc
= NULL
;
677 cc
= cescape(u
->name
);
681 p
= strjoina("/var/lib/systemd/linger/", cc
);
683 return access(p
, F_OK
) >= 0;
686 bool user_check_gc(User
*u
, bool drop_not_started
) {
689 if (drop_not_started
&& !u
->started
)
695 if (user_check_linger_file(u
) > 0)
698 if (u
->slice_job
&& manager_job_is_active(u
->manager
, u
->slice_job
))
701 if (u
->service_job
&& manager_job_is_active(u
->manager
, u
->service_job
))
707 void user_add_to_gc_queue(User
*u
) {
713 LIST_PREPEND(gc_queue
, u
->manager
->user_gc_queue
, u
);
714 u
->in_gc_queue
= true;
717 UserState
user_get_state(User
*u
) {
725 if (!u
->started
|| u
->slice_job
|| u
->service_job
)
729 bool all_closing
= true;
731 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
734 state
= session_get_state(i
);
735 if (state
== SESSION_ACTIVE
)
737 if (state
!= SESSION_CLOSING
)
741 return all_closing
? USER_CLOSING
: USER_ONLINE
;
744 if (user_check_linger_file(u
) > 0)
745 return USER_LINGERING
;
750 int user_kill(User
*u
, int signo
) {
753 return manager_kill_unit(u
->manager
, u
->slice
, KILL_ALL
, signo
, NULL
);
756 static bool elect_display_filter(Session
*s
) {
757 /* Return true if the session is a candidate for the user’s ‘primary
758 * session’ or ‘display’. */
761 return (s
->class == SESSION_USER
&& !s
->stopping
);
764 static int elect_display_compare(Session
*s1
, Session
*s2
) {
765 /* Indexed by SessionType. Lower numbers mean more preferred. */
766 const int type_ranks
[_SESSION_TYPE_MAX
] = {
767 [SESSION_UNSPECIFIED
] = 0,
770 [SESSION_WAYLAND
] = -3,
775 /* Calculate the partial order relationship between s1 and s2,
776 * returning < 0 if s1 is preferred as the user’s ‘primary session’,
777 * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
780 * s1 or s2 may be NULL. */
784 if ((s1
== NULL
) != (s2
== NULL
))
785 return (s1
== NULL
) - (s2
== NULL
);
787 if (s1
->stopping
!= s2
->stopping
)
788 return s1
->stopping
- s2
->stopping
;
790 if ((s1
->class != SESSION_USER
) != (s2
->class != SESSION_USER
))
791 return (s1
->class != SESSION_USER
) - (s2
->class != SESSION_USER
);
793 if ((s1
->type
== _SESSION_TYPE_INVALID
) != (s2
->type
== _SESSION_TYPE_INVALID
))
794 return (s1
->type
== _SESSION_TYPE_INVALID
) - (s2
->type
== _SESSION_TYPE_INVALID
);
796 if (s1
->type
!= s2
->type
)
797 return type_ranks
[s1
->type
] - type_ranks
[s2
->type
];
802 void user_elect_display(User
*u
) {
807 /* This elects a primary session for each user, which we call
808 * the "display". We try to keep the assignment stable, but we
809 * "upgrade" to better choices. */
810 log_debug("Electing new display for user %s", u
->name
);
812 LIST_FOREACH(sessions_by_user
, s
, u
->sessions
) {
813 if (!elect_display_filter(s
)) {
814 log_debug("Ignoring session %s", s
->id
);
818 if (elect_display_compare(s
, u
->display
) < 0) {
819 log_debug("Choosing session %s in preference to %s", s
->id
, u
->display
? u
->display
->id
: "-");
825 static const char* const user_state_table
[_USER_STATE_MAX
] = {
826 [USER_OFFLINE
] = "offline",
827 [USER_OPENING
] = "opening",
828 [USER_LINGERING
] = "lingering",
829 [USER_ONLINE
] = "online",
830 [USER_ACTIVE
] = "active",
831 [USER_CLOSING
] = "closing"
834 DEFINE_STRING_TABLE_LOOKUP(user_state
, UserState
);
836 int config_parse_tmpfs_size(
838 const char *filename
,
841 unsigned section_line
,
856 /* First, try to parse as percentage */
857 r
= parse_percent(rvalue
);
858 if (r
> 0 && r
< 100)
859 *sz
= physical_memory_scale(r
, 100U);
863 /* If the passed argument was not a percentage, or out of range, parse as byte size */
865 r
= parse_size(rvalue
, 1024, &k
);
866 if (r
< 0 || k
<= 0 || (uint64_t) (size_t) k
!= k
) {
867 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse size value, ignoring: %s", rvalue
);
871 *sz
= PAGE_ALIGN((size_t) k
);
877 int config_parse_user_tasks_max(
879 const char *filename
,
882 unsigned section_line
,
898 if (isempty(rvalue
)) {
899 *m
= system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE
, 100U);
903 if (streq(rvalue
, "infinity")) {
904 *m
= CGROUP_LIMIT_MAX
;
908 /* Try to parse as percentage */
909 r
= parse_percent(rvalue
);
911 k
= system_tasks_max_scale(r
, 100U);
914 /* If the passed argument was not a percentage, or out of range, parse as byte size */
916 r
= safe_atou64(rvalue
, &k
);
918 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse tasks maximum, ignoring: %s", rvalue
);
923 if (k
<= 0 || k
>= UINT64_MAX
) {
924 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Tasks maximum out of range, ignoring: %s", rvalue
);