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