From 675752d11fd2fd1708d42a90b618a9556688a20a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 8 Aug 2018 15:27:49 +0200 Subject: logind: add a RequiresMountsFor= dependency from the session scope unit to the home directory of the user This is useful so that during shutdown scope units are always terminated before the mounts necessary for the home directory. (Ideally we'd also add a similar dependency from the user@.service instance to the home directory, but this isn't as easy as that service is defined statically and not dynamically, and hence not easy to modify dynamically, in particular when it comes to deps) (cherry picked from commit d5ac9d060267820aabdf9af509a54a1830b27b7d) --- src/login/logind-core.c | 24 ++++++++++++++++++------ src/login/logind-dbus.c | 7 +++++++ src/login/logind-session.c | 1 + src/login/logind-user.c | 15 ++++++++++++++- src/login/logind-user.h | 3 ++- src/login/logind.h | 4 ++-- 6 files changed, 44 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/login/logind-core.c b/src/login/logind-core.c index f9a07b54a..1d85278c6 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -146,7 +146,14 @@ int manager_add_session(Manager *m, const char *id, Session **_session) { return 0; } -int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) { +int manager_add_user( + Manager *m, + uid_t uid, + gid_t gid, + const char *name, + const char *home, + User **_user) { + User *u; int r; @@ -155,7 +162,7 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User ** u = hashmap_get(m->users, UID_TO_PTR(uid)); if (!u) { - r = user_new(&u, m, uid, gid, name); + r = user_new(&u, m, uid, gid, name, home); if (r < 0) return r; } @@ -166,7 +173,12 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User ** return 0; } -int manager_add_user_by_name(Manager *m, const char *name, User **_user) { +int manager_add_user_by_name( + Manager *m, + const char *name, + User **_user) { + + const char *home = NULL; uid_t uid; gid_t gid; int r; @@ -174,11 +186,11 @@ int manager_add_user_by_name(Manager *m, const char *name, User **_user) { assert(m); assert(name); - r = get_user_creds(&name, &uid, &gid, NULL, NULL); + r = get_user_creds(&name, &uid, &gid, &home, NULL); if (r < 0) return r; - return manager_add_user(m, uid, gid, name, _user); + return manager_add_user(m, uid, gid, name, home, _user); } int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) { @@ -191,7 +203,7 @@ int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) { if (!p) return errno > 0 ? -errno : -ENOENT; - return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user); + return manager_add_user(m, uid, p->pw_gid, p->pw_name, p->pw_dir, _user); } int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) { diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 98228c74b..872bcf881 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -3110,6 +3110,7 @@ int manager_start_scope( const char *description, char **wants, char **after, + const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job) { @@ -3165,6 +3166,12 @@ int manager_start_scope( return r; } + if (!empty_or_root(requires_mounts_for)) { + r = sd_bus_message_append(m, "(sv)", "RequiresMountsFor", "as", 1, requires_mounts_for); + if (r < 0) + return r; + } + /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore * SIGTERM */ r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true); diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 6e65c0bb5..27dcf83a6 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -653,6 +653,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er description, STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */ STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */ + s->user->home, properties, error, &s->scope_job); diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 1e9048600..8cc407c20 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -32,7 +32,13 @@ /// Additional includes needed by elogind #include "user-runtime-dir.h" -int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) { +int user_new(User **ret, + Manager *m, + uid_t uid, + gid_t gid, + const char *name, + const char *home) { + _cleanup_(user_freep) User *u = NULL; char lu[DECIMAL_STR_MAX(uid_t) + 1]; int r; @@ -56,6 +62,10 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) { if (!u->name) return -ENOMEM; + u->home = strdup(home); + if (!u->home) + return -ENOMEM; + if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0) return -ENOMEM; @@ -128,6 +138,7 @@ User *user_free(User *u) { u->runtime_path = mfree(u->runtime_path); u->state_file = mfree(u->state_file); u->name = mfree(u->name); + u->home = mfree(u->home); return mfree(u); } @@ -348,6 +359,7 @@ static void user_start_service(User *u) { #else assert(u); /* Start the service containing the "systemd --user" instance (user@.service). Note that we don't explicitly + * start the per-user slice or the elogind-runtime-dir@.service instance, as those are pulled in both by * start the per-user slice or the elogind-runtime-dir@.service instance, as those are pulled in both by * start the per-user slice or the elogind-runtime-dir@.service instance, as those are pulled in both by * user@.service and the session scopes as dependencies. */ @@ -390,6 +402,7 @@ int user_start(User *u) { /* Save the user data so far, because pam_systemd will read the XDG_RUNTIME_DIR out of it while starting up * elogind --user. We need to do user_save_internal() because we have not "officially" started yet. */ * elogind --user. We need to do user_save_internal() because we have not "officially" started yet. */ + * elogind --user. We need to do user_save_internal() because we have not "officially" started yet. */ user_save_internal(u); /* Spawn user systemd */ diff --git a/src/login/logind-user.h b/src/login/logind-user.h index a1a8c632d..ca404f31b 100644 --- a/src/login/logind-user.h +++ b/src/login/logind-user.h @@ -23,6 +23,7 @@ struct User { uid_t uid; gid_t gid; char *name; + char *home; char *state_file; char *runtime_path; @@ -51,7 +52,7 @@ struct User { LIST_FIELDS(User, gc_queue); }; -int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name); +int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name, const char *home); User *user_free(User *u); DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free); diff --git a/src/login/logind.h b/src/login/logind.h index 7f3452591..4c061a3cb 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -177,7 +177,7 @@ int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_dev int manager_add_button(Manager *m, const char *name, Button **_button); int manager_add_seat(Manager *m, const char *id, Seat **_seat); int manager_add_session(Manager *m, const char *id, Session **_session); -int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user); +int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, const char *home, User **_user); int manager_add_user_by_name(Manager *m, const char *name, User **_user); int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user); int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor); @@ -222,7 +222,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, HandleAction action, int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_; #if 0 /// UNNEEDED by elogind -int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, sd_bus_message *more_properties, sd_bus_error *error, char **job); +int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job); int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error); -- cgit v1.2.3