b12df0
From e9a187ea6abf1e7034ee3113355b282743a98f39 Mon Sep 17 00:00:00 2001
b12df0
From: Lennart Poettering <lennart@poettering.net>
b12df0
Date: Wed, 8 Aug 2018 15:27:49 +0200
b12df0
Subject: [PATCH] logind: add a RequiresMountsFor= dependency from the session
b12df0
 scope unit to the home directory of the user
b12df0
b12df0
This is useful so that during shutdown scope units are always terminated
b12df0
before the mounts necessary for the home directory.
b12df0
b12df0
(Ideally we'd also add a similar dependency from the user@.service
b12df0
instance to the home directory, but this isn't as easy as that service
b12df0
is defined statically and not dynamically, and hence not easy to modify
b12df0
dynamically, in particular when it comes to deps)
b12df0
b12df0
(cherry picked from commit d5ac9d060267820aabdf9af509a54a1830b27b7d)
b12df0
b12df0
Related: #1642460
b12df0
---
b12df0
 src/login/logind-core.c    | 24 ++++++++++++++++++------
b12df0
 src/login/logind-dbus.c    |  7 +++++++
b12df0
 src/login/logind-session.c |  1 +
b12df0
 src/login/logind-user.c    | 13 ++++++++++++-
b12df0
 src/login/logind-user.h    |  3 ++-
b12df0
 src/login/logind.h         |  4 ++--
b12df0
 6 files changed, 42 insertions(+), 10 deletions(-)
b12df0
b12df0
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
b12df0
index 678c708df1..0ed812a2c8 100644
b12df0
--- a/src/login/logind-core.c
b12df0
+++ b/src/login/logind-core.c
b12df0
@@ -128,7 +128,14 @@ int manager_add_session(Manager *m, const char *id, Session **_session) {
b12df0
         return 0;
b12df0
 }
b12df0
 
b12df0
-int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
b12df0
+int manager_add_user(
b12df0
+                Manager *m,
b12df0
+                uid_t uid,
b12df0
+                gid_t gid,
b12df0
+                const char *name,
b12df0
+                const char *home,
b12df0
+                User **_user) {
b12df0
+
b12df0
         User *u;
b12df0
         int r;
b12df0
 
b12df0
@@ -137,7 +144,7 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **
b12df0
 
b12df0
         u = hashmap_get(m->users, UID_TO_PTR(uid));
b12df0
         if (!u) {
b12df0
-                r = user_new(&u, m, uid, gid, name);
b12df0
+                r = user_new(&u, m, uid, gid, name, home);
b12df0
                 if (r < 0)
b12df0
                         return r;
b12df0
         }
b12df0
@@ -148,7 +155,12 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **
b12df0
         return 0;
b12df0
 }
b12df0
 
b12df0
-int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
b12df0
+int manager_add_user_by_name(
b12df0
+                Manager *m,
b12df0
+                const char *name,
b12df0
+                User **_user) {
b12df0
+
b12df0
+        const char *home = NULL;
b12df0
         uid_t uid;
b12df0
         gid_t gid;
b12df0
         int r;
b12df0
@@ -156,11 +168,11 @@ int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
b12df0
         assert(m);
b12df0
         assert(name);
b12df0
 
b12df0
-        r = get_user_creds(&name, &uid, &gid, NULL, NULL);
b12df0
+        r = get_user_creds(&name, &uid, &gid, &home, NULL);
b12df0
         if (r < 0)
b12df0
                 return r;
b12df0
 
b12df0
-        return manager_add_user(m, uid, gid, name, _user);
b12df0
+        return manager_add_user(m, uid, gid, name, home, _user);
b12df0
 }
b12df0
 
b12df0
 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
b12df0
@@ -173,7 +185,7 @@ int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
b12df0
         if (!p)
b12df0
                 return errno > 0 ? -errno : -ENOENT;
b12df0
 
b12df0
-        return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
b12df0
+        return manager_add_user(m, uid, p->pw_gid, p->pw_name, p->pw_dir, _user);
b12df0
 }
b12df0
 
b12df0
 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
b12df0
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
b12df0
index 6586280269..1bb152bc20 100644
b12df0
--- a/src/login/logind-dbus.c
b12df0
+++ b/src/login/logind-dbus.c
b12df0
@@ -3313,6 +3313,7 @@ int manager_start_scope(
b12df0
                 const char *description,
b12df0
                 char **wants,
b12df0
                 char **after,
b12df0
+                const char *requires_mounts_for,
b12df0
                 sd_bus_message *more_properties,
b12df0
                 sd_bus_error *error,
b12df0
                 char **job) {
b12df0
@@ -3368,6 +3369,12 @@ int manager_start_scope(
b12df0
                         return r;
b12df0
         }
b12df0
 
b12df0
+        if (!empty_or_root(requires_mounts_for)) {
b12df0
+                r = sd_bus_message_append(m, "(sv)", "RequiresMountsFor", "as", 1, requires_mounts_for);
b12df0
+                if (r < 0)
b12df0
+                        return r;
b12df0
+        }
b12df0
+
b12df0
         /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore
b12df0
          * SIGTERM */
b12df0
         r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
b12df0
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
b12df0
index dd4ac9482a..e4c8bb36f6 100644
b12df0
--- a/src/login/logind-session.c
b12df0
+++ b/src/login/logind-session.c
b12df0
@@ -591,6 +591,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er
b12df0
                                 description,
b12df0
                                 STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */
b12df0
                                 STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */
b12df0
+                                s->user->home,
b12df0
                                 properties,
b12df0
                                 error,
b12df0
                                 &s->scope_job);
b12df0
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
b12df0
index f23fcbe674..70f5eb9d59 100644
b12df0
--- a/src/login/logind-user.c
b12df0
+++ b/src/login/logind-user.c
b12df0
@@ -30,7 +30,13 @@
b12df0
 #include "user-util.h"
b12df0
 #include "util.h"
b12df0
 
b12df0
-int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
b12df0
+int user_new(User **ret,
b12df0
+             Manager *m,
b12df0
+             uid_t uid,
b12df0
+             gid_t gid,
b12df0
+             const char *name,
b12df0
+             const char *home) {
b12df0
+
b12df0
         _cleanup_(user_freep) User *u = NULL;
b12df0
         char lu[DECIMAL_STR_MAX(uid_t) + 1];
b12df0
         int r;
b12df0
@@ -54,6 +60,10 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
b12df0
         if (!u->name)
b12df0
                 return -ENOMEM;
b12df0
 
b12df0
+        u->home = strdup(home);
b12df0
+        if (!u->home)
b12df0
+                return -ENOMEM;
b12df0
+
b12df0
         if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
b12df0
                 return -ENOMEM;
b12df0
 
b12df0
@@ -124,6 +134,7 @@ User *user_free(User *u) {
b12df0
         u->runtime_path = mfree(u->runtime_path);
b12df0
         u->state_file = mfree(u->state_file);
b12df0
         u->name = mfree(u->name);
b12df0
+        u->home = mfree(u->home);
b12df0
 
b12df0
         return mfree(u);
b12df0
 }
b12df0
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
b12df0
index e05646adc9..c41973e27d 100644
b12df0
--- a/src/login/logind-user.h
b12df0
+++ b/src/login/logind-user.h
b12df0
@@ -23,6 +23,7 @@ struct User {
b12df0
         uid_t uid;
b12df0
         gid_t gid;
b12df0
         char *name;
b12df0
+        char *home;
b12df0
         char *state_file;
b12df0
         char *runtime_path;
b12df0
 
b12df0
@@ -49,7 +50,7 @@ struct User {
b12df0
         LIST_FIELDS(User, gc_queue);
b12df0
 };
b12df0
 
b12df0
-int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name);
b12df0
+int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name, const char *home);
b12df0
 User *user_free(User *u);
b12df0
 
b12df0
 DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free);
b12df0
diff --git a/src/login/logind.h b/src/login/logind.h
b12df0
index 7288dd7445..d29b01c75b 100644
b12df0
--- a/src/login/logind.h
b12df0
+++ b/src/login/logind.h
b12df0
@@ -129,7 +129,7 @@ int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_dev
b12df0
 int manager_add_button(Manager *m, const char *name, Button **_button);
b12df0
 int manager_add_seat(Manager *m, const char *id, Seat **_seat);
b12df0
 int manager_add_session(Manager *m, const char *id, Session **_session);
b12df0
-int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user);
b12df0
+int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, const char *home, User **_user);
b12df0
 int manager_add_user_by_name(Manager *m, const char *name, User **_user);
b12df0
 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user);
b12df0
 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor);
b12df0
@@ -162,7 +162,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
b12df0
 
b12df0
 int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
b12df0
 
b12df0
-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);
b12df0
+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);
b12df0
 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
b12df0
 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
b12df0
 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);