]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-user.c
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"
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);
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("SESSIONS=", f
);
188 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
197 fputs("\nSEATS=", f
);
199 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
208 fputs(i
->seat
->id
, f
);
211 fputs("\nACTIVE_SESSIONS=", f
);
213 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
214 if (!session_is_active(i
))
225 fputs("\nONLINE_SESSIONS=", f
);
227 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
228 if (session_get_state(i
) == SESSION_CLOSING
)
239 fputs("\nACTIVE_SEATS=", f
);
241 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
242 if (!session_is_active(i
) || !i
->seat
)
250 fputs(i
->seat
->id
, f
);
253 fputs("\nONLINE_SEATS=", f
);
255 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
256 if (session_get_state(i
) == SESSION_CLOSING
|| !i
->seat
)
264 fputs(i
->seat
->id
, 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 log_error_errno(r
, "Failed to read %s: %m", u
->state_file
);
321 s
= hashmap_get(u
->manager
->sessions
, display
);
323 if (s
&& s
->display
&& display_is_local(s
->display
))
327 unsigned long long l
;
328 if (sscanf(realtime
, "%llu", &l
) > 0)
329 u
->timestamp
.realtime
= l
;
333 unsigned long long l
;
334 if (sscanf(monotonic
, "%llu", &l
) > 0)
335 u
->timestamp
.monotonic
= l
;
341 static int user_mkdir_runtime_path(User
*u
) {
346 r
= mkdir_safe_label("/run/user", 0755, 0, 0);
348 return log_error_errno(r
, "Failed to create /run/user: %m");
350 if (path_is_mount_point(u
->runtime_path
, 0) <= 0) {
351 _cleanup_free_
char *t
= NULL
;
353 (void) mkdir_label(u
->runtime_path
, 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", u
->runtime_path
, "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", u
->runtime_path
);
371 /* Lacking permissions, maybe
372 * CAP_SYS_ADMIN-less container? In this case,
373 * just use a normal directory. */
375 r
= chmod_and_chown(u
->runtime_path
, 0700, u
->uid
, u
->gid
);
377 log_error_errno(r
, "Failed to change runtime directory ownership and mode: %m");
382 r
= label_fix(u
->runtime_path
, false, false);
384 log_warning_errno(r
, "Failed to fix label of '%s', ignoring: %m", u
->runtime_path
);
390 /* Try to clean up, but ignore errors */
391 (void) rmdir(u
->runtime_path
);
395 static int user_start_slice(User
*u
) {
396 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
397 const char *description
;
403 u
->slice_job
= mfree(u
->slice_job
);
404 description
= strjoina("User Slice of ", u
->name
);
406 r
= manager_start_slice(
410 "systemd-logind.service",
411 "systemd-user-sessions.service",
412 u
->manager
->user_tasks_max
,
417 else if (!sd_bus_error_has_name(&error
, BUS_ERROR_UNIT_EXISTS
))
418 /* we don't fail due to this, let's try to continue */
419 log_error_errno(r
, "Failed to start user slice %s, ignoring: %s (%s)",
420 u
->slice
, bus_error_message(&error
, r
), error
.name
);
425 static int user_start_service(User
*u
) {
426 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
432 u
->service_job
= mfree(u
->service_job
);
434 r
= manager_start_unit(
440 /* we don't fail due to this, let's try to continue */
441 log_error_errno(r
, "Failed to start user service, ignoring: %s", bus_error_message(&error
, r
));
443 u
->service_job
= job
;
449 int user_start(User
*u
) {
454 if (u
->started
&& !u
->stopping
)
458 * If u->stopping is set, the user is marked for removal and the slice
459 * and service stop-jobs are queued. We have to clear that flag before
460 * queing the start-jobs again. If they succeed, the user object can be
461 * re-used just fine (pid1 takes care of job-ordering and proper
462 * restart), but if they fail, we want to force another user_stop() so
463 * possibly pending units are stopped.
464 * Note that we don't clear u->started, as we have no clue what state
465 * the user is in on failure here. Hence, we pretend the user is
466 * running so it will be properly taken down by GC. However, we clearly
467 * return an error from user_start() in that case, so no further
468 * reference to the user is taken.
473 log_debug("New user %s logged in.", u
->name
);
475 /* Make XDG_RUNTIME_DIR */
476 r
= user_mkdir_runtime_path(u
);
482 r
= user_start_slice(u
);
486 /* Save the user data so far, because pam_systemd will read the
487 * XDG_RUNTIME_DIR out of it while starting up systemd --user.
488 * We need to do user_save_internal() because we have not
489 * "officially" started yet. */
490 user_save_internal(u
);
492 /* Spawn user systemd */
493 r
= user_start_service(u
);
498 if (!dual_timestamp_is_set(&u
->timestamp
))
499 dual_timestamp_get(&u
->timestamp
);
500 user_send_signal(u
, true);
504 /* Save new user data */
510 static int user_stop_slice(User
*u
) {
511 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
517 r
= manager_stop_unit(u
->manager
, u
->slice
, &error
, &job
);
519 log_error("Failed to stop user slice: %s", bus_error_message(&error
, r
));
529 static int user_stop_service(User
*u
) {
530 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
536 r
= manager_stop_unit(u
->manager
, u
->service
, &error
, &job
);
538 log_error("Failed to stop user service: %s", bus_error_message(&error
, r
));
542 free(u
->service_job
);
543 u
->service_job
= job
;
548 static int user_remove_runtime_path(User
*u
) {
553 r
= rm_rf(u
->runtime_path
, 0);
555 log_error_errno(r
, "Failed to remove runtime directory %s: %m", u
->runtime_path
);
557 /* Ignore cases where the directory isn't mounted, as that's
558 * quite possible, if we lacked the permissions to mount
560 r
= umount2(u
->runtime_path
, MNT_DETACH
);
561 if (r
< 0 && errno
!= EINVAL
&& errno
!= ENOENT
)
562 log_error_errno(errno
, "Failed to unmount user runtime directory %s: %m", u
->runtime_path
);
564 r
= rm_rf(u
->runtime_path
, REMOVE_ROOT
);
566 log_error_errno(r
, "Failed to remove runtime directory %s: %m", u
->runtime_path
);
571 int user_stop(User
*u
, bool force
) {
576 /* Stop jobs have already been queued */
582 LIST_FOREACH(sessions_by_user
, s
, u
->sessions
) {
583 k
= session_stop(s
, force
);
589 k
= user_stop_service(u
);
594 k
= user_stop_slice(u
);
605 int user_finalize(User
*u
) {
612 log_debug("User %s logged out.", u
->name
);
614 LIST_FOREACH(sessions_by_user
, s
, u
->sessions
) {
615 k
= session_finalize(s
);
620 /* Kill XDG_RUNTIME_DIR */
621 k
= user_remove_runtime_path(u
);
625 /* Clean SysV + POSIX IPC objects */
626 if (u
->manager
->remove_ipc
) {
627 k
= clean_ipc(u
->uid
);
632 unlink(u
->state_file
);
633 user_add_to_gc_queue(u
);
636 user_send_signal(u
, false);
643 int user_get_idle_hint(User
*u
, dual_timestamp
*t
) {
645 bool idle_hint
= true;
646 dual_timestamp ts
= DUAL_TIMESTAMP_NULL
;
650 LIST_FOREACH(sessions_by_user
, s
, u
->sessions
) {
654 ih
= session_get_idle_hint(s
, &k
);
660 if (k
.monotonic
< ts
.monotonic
)
666 } else if (idle_hint
) {
668 if (k
.monotonic
> ts
.monotonic
)
679 int user_check_linger_file(User
*u
) {
680 _cleanup_free_
char *cc
= NULL
;
683 cc
= cescape(u
->name
);
687 p
= strjoina("/var/lib/systemd/linger/", cc
);
689 return access(p
, F_OK
) >= 0;
692 bool user_check_gc(User
*u
, bool drop_not_started
) {
695 if (drop_not_started
&& !u
->started
)
701 if (user_check_linger_file(u
) > 0)
704 if (u
->slice_job
&& manager_job_is_active(u
->manager
, u
->slice_job
))
707 if (u
->service_job
&& manager_job_is_active(u
->manager
, u
->service_job
))
713 void user_add_to_gc_queue(User
*u
) {
719 LIST_PREPEND(gc_queue
, u
->manager
->user_gc_queue
, u
);
720 u
->in_gc_queue
= true;
723 UserState
user_get_state(User
*u
) {
731 if (!u
->started
|| u
->slice_job
|| u
->service_job
)
735 bool all_closing
= true;
737 LIST_FOREACH(sessions_by_user
, i
, u
->sessions
) {
740 state
= session_get_state(i
);
741 if (state
== SESSION_ACTIVE
)
743 if (state
!= SESSION_CLOSING
)
747 return all_closing
? USER_CLOSING
: USER_ONLINE
;
750 if (user_check_linger_file(u
) > 0)
751 return USER_LINGERING
;
756 int user_kill(User
*u
, int signo
) {
759 return manager_kill_unit(u
->manager
, u
->slice
, KILL_ALL
, signo
, NULL
);
762 static bool elect_display_filter(Session
*s
) {
763 /* Return true if the session is a candidate for the user’s ‘primary
764 * session’ or ‘display’. */
767 return (s
->class == SESSION_USER
&& !s
->stopping
);
770 static int elect_display_compare(Session
*s1
, Session
*s2
) {
771 /* Indexed by SessionType. Lower numbers mean more preferred. */
772 const int type_ranks
[_SESSION_TYPE_MAX
] = {
773 [SESSION_UNSPECIFIED
] = 0,
776 [SESSION_WAYLAND
] = -3,
781 /* Calculate the partial order relationship between s1 and s2,
782 * returning < 0 if s1 is preferred as the user’s ‘primary session’,
783 * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
786 * s1 or s2 may be NULL. */
790 if ((s1
== NULL
) != (s2
== NULL
))
791 return (s1
== NULL
) - (s2
== NULL
);
793 if (s1
->stopping
!= s2
->stopping
)
794 return s1
->stopping
- s2
->stopping
;
796 if ((s1
->class != SESSION_USER
) != (s2
->class != SESSION_USER
))
797 return (s1
->class != SESSION_USER
) - (s2
->class != SESSION_USER
);
799 if ((s1
->type
== _SESSION_TYPE_INVALID
) != (s2
->type
== _SESSION_TYPE_INVALID
))
800 return (s1
->type
== _SESSION_TYPE_INVALID
) - (s2
->type
== _SESSION_TYPE_INVALID
);
802 if (s1
->type
!= s2
->type
)
803 return type_ranks
[s1
->type
] - type_ranks
[s2
->type
];
808 void user_elect_display(User
*u
) {
813 /* This elects a primary session for each user, which we call
814 * the "display". We try to keep the assignment stable, but we
815 * "upgrade" to better choices. */
816 log_debug("Electing new display for user %s", u
->name
);
818 LIST_FOREACH(sessions_by_user
, s
, u
->sessions
) {
819 if (!elect_display_filter(s
)) {
820 log_debug("Ignoring session %s", s
->id
);
824 if (elect_display_compare(s
, u
->display
) < 0) {
825 log_debug("Choosing session %s in preference to %s", s
->id
, u
->display
? u
->display
->id
: "-");
831 static const char* const user_state_table
[_USER_STATE_MAX
] = {
832 [USER_OFFLINE
] = "offline",
833 [USER_OPENING
] = "opening",
834 [USER_LINGERING
] = "lingering",
835 [USER_ONLINE
] = "online",
836 [USER_ACTIVE
] = "active",
837 [USER_CLOSING
] = "closing"
840 DEFINE_STRING_TABLE_LOOKUP(user_state
, UserState
);
842 int config_parse_tmpfs_size(
844 const char *filename
,
847 unsigned section_line
,
863 e
= endswith(rvalue
, "%");
869 ul
= strtoul(rvalue
, &f
, 10);
870 if (errno
> 0 || f
!= e
) {
871 log_syntax(unit
, LOG_ERR
, filename
, line
, errno
, "Failed to parse percentage value, ignoring: %s", rvalue
);
875 if (ul
<= 0 || ul
>= 100) {
876 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Percentage value out of range, ignoring: %s", rvalue
);
880 *sz
= PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul
) / (uint64_t) 100));
884 r
= parse_size(rvalue
, 1024, &k
);
885 if (r
< 0 || (uint64_t) (size_t) k
!= k
) {
886 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse size value, ignoring: %s", rvalue
);
890 *sz
= PAGE_ALIGN((size_t) k
);