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