]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homed: allow overriding the root directory for home dirs via env var (i.e. use a...
authorLennart Poettering <lennart@poettering.net>
Thu, 7 Oct 2021 20:20:25 +0000 (22:20 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 11 Oct 2021 14:00:34 +0000 (16:00 +0200)
This is a debugging feature. It's sometimes incredibly useful to be able
to run a second instance of homed that operates on another dir than
/home/.

Specifically, if you build homed from the source tree you can now run an
instance of it pretty reasonably directly from the build tree via:

  sudo SYSTEMD_HOME_DEBUG_SUFFIX=foo SYSTEMD_HOMEWORK_PATH=$(pwd)/build/systemd-homework SYSTEMD_HOME_ROOT=/home/foo ./build/systemd-homed

And then talk to it via

  sudo SYSTEMD_HOME_DEBUG_SUFFIX=foo homectl …

(you might need to tweak your dbus policy for this to work fully though)

src/basic/user-util.c
src/basic/user-util.h
src/home/homed-manager.c
src/home/homework.c
src/home/user-record-util.c
src/shared/user-record.c

index 385ec514b4171832aa948be95a2f658febc7fffb..aee2d9dc595a24a7936b07db5cb5538a11cdf80b 100644 (file)
@@ -1085,3 +1085,14 @@ int is_this_me(const char *username) {
 
         return uid == getuid();
 }
+
+const char *get_home_root(void) {
+        const char *e;
+
+        /* For debug purposes allow overriding where we look for home dirs */
+        e = secure_getenv("SYSTEMD_HOME_ROOT");
+        if (e && path_is_absolute(e) && path_is_normalized(e))
+                return e;
+
+        return "/home";
+}
index fd00b47b7665c55ced366dd2e57d259bdc6302e2..ab1ce48b2df8e8b0d2cbe700fae9549b19bdf97f 100644 (file)
@@ -112,6 +112,8 @@ bool is_nologin_shell(const char *shell);
 
 int is_this_me(const char *username);
 
+const char *get_home_root(void);
+
 /* A locked *and* invalid password for "struct spwd"'s .sp_pwdp and "struct passwd"'s .pw_passwd field */
 #define PASSWORD_LOCKED_AND_INVALID "!*"
 
index 39782304f642c69dcab5d175239ba5faa7a543b3..38283ff1ede8e5daed5d57ed2954d4c4a68568d6 100644 (file)
@@ -83,35 +83,38 @@ static void manager_watch_home(Manager *m) {
         m->inotify_event_source = sd_event_source_disable_unref(m->inotify_event_source);
         m->scan_slash_home = false;
 
-        if (statfs("/home/", &sfs) < 0) {
+        if (statfs(get_home_root(), &sfs) < 0) {
                 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
-                               "Failed to statfs() /home/ directory, disabling automatic scanning.");
+                               "Failed to statfs() %s directory, disabling automatic scanning.", get_home_root());
                 return;
         }
 
         if (is_network_fs(&sfs)) {
-                log_info("/home/ is a network file system, disabling automatic scanning.");
+                log_info("%s is a network file system, disabling automatic scanning.", get_home_root());
                 return;
         }
 
         if (is_fs_type(&sfs, AUTOFS_SUPER_MAGIC)) {
-                log_info("/home/ is on autofs, disabling automatic scanning.");
+                log_info("%s is on autofs, disabling automatic scanning.", get_home_root());
                 return;
         }
 
         m->scan_slash_home = true;
 
-        r = sd_event_add_inotify(m->event, &m->inotify_event_source, "/home/",
+        r = sd_event_add_inotify(m->event, &m->inotify_event_source, get_home_root(),
                                  IN_CREATE|IN_CLOSE_WRITE|IN_DELETE_SELF|IN_MOVE_SELF|IN_ONLYDIR|IN_MOVED_TO|IN_MOVED_FROM|IN_DELETE,
                                  on_home_inotify, m);
         if (r < 0)
                 log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
-                               "Failed to create inotify watch on /home/, ignoring.");
+                               "Failed to create inotify watch on %s, ignoring.", get_home_root());
 
         (void) sd_event_source_set_description(m->inotify_event_source, "home-inotify");
+
+        log_info("Watching %s.", get_home_root());
 }
 
 static int on_home_inotify(sd_event_source *s, const struct inotify_event *event, void *userdata) {
+        _cleanup_free_ char *j = NULL;
         Manager *m = userdata;
         const char *e, *n;
 
@@ -121,15 +124,15 @@ static int on_home_inotify(sd_event_source *s, const struct inotify_event *event
         if ((event->mask & (IN_Q_OVERFLOW|IN_MOVE_SELF|IN_DELETE_SELF|IN_IGNORED|IN_UNMOUNT)) != 0) {
 
                 if (FLAGS_SET(event->mask, IN_Q_OVERFLOW))
-                        log_debug("/home/ inotify queue overflow, rescanning.");
+                        log_debug("%s inotify queue overflow, rescanning.", get_home_root());
                 else if (FLAGS_SET(event->mask, IN_MOVE_SELF))
-                        log_info("/home/ moved or renamed, recreating watch and rescanning.");
+                        log_info("%s moved or renamed, recreating watch and rescanning.", get_home_root());
                 else if (FLAGS_SET(event->mask, IN_DELETE_SELF))
-                        log_info("/home/ deleted, recreating watch and rescanning.");
+                        log_info("%s deleted, recreating watch and rescanning.", get_home_root());
                 else if (FLAGS_SET(event->mask, IN_UNMOUNT))
-                        log_info("/home/ unmounted, recreating watch and rescanning.");
+                        log_info("%s unmounted, recreating watch and rescanning.", get_home_root());
                 else if (FLAGS_SET(event->mask, IN_IGNORED))
-                        log_info("/home/ watch invalidated, recreating watch and rescanning.");
+                        log_info("%s watch invalidated, recreating watch and rescanning.", get_home_root());
 
                 manager_watch_home(m);
                 (void) manager_gc_images(m);
@@ -150,15 +153,19 @@ static int on_home_inotify(sd_event_source *s, const struct inotify_event *event
         if (!suitable_user_name(n))
                 return 0;
 
+        j = path_join(get_home_root(), event->name);
+        if (!j)
+                return log_oom();
+
         if ((event->mask & (IN_CREATE|IN_CLOSE_WRITE|IN_MOVED_TO)) != 0) {
                 if (FLAGS_SET(event->mask, IN_CREATE))
-                        log_debug("/home/%s has been created, having a look.", event->name);
+                        log_debug("%s has been created, having a look.", j);
                 else if (FLAGS_SET(event->mask, IN_CLOSE_WRITE))
-                        log_debug("/home/%s has been modified, having a look.", event->name);
+                        log_debug("%s has been modified, having a look.", j);
                 else if (FLAGS_SET(event->mask, IN_MOVED_TO))
-                        log_debug("/home/%s has been moved in, having a look.", event->name);
+                        log_debug("%s has been moved in, having a look.", j);
 
-                (void) manager_assess_image(m, -1, "/home/", event->name);
+                (void) manager_assess_image(m, -1, get_home_root(), event->name);
                 (void) bus_manager_emit_auto_login_changed(m);
         }
 
@@ -166,11 +173,11 @@ static int on_home_inotify(sd_event_source *s, const struct inotify_event *event
                 Home *h;
 
                 if (FLAGS_SET(event->mask, IN_DELETE))
-                        log_debug("/home/%s has been deleted, revalidating.", event->name);
+                        log_debug("%s has been deleted, revalidating.", j);
                 else if (FLAGS_SET(event->mask, IN_CLOSE_WRITE))
-                        log_debug("/home/%s has been closed after writing, revalidating.", event->name);
+                        log_debug("%s has been closed after writing, revalidating.", j);
                 else if (FLAGS_SET(event->mask, IN_MOVED_FROM))
-                        log_debug("/home/%s has been moved away, revalidating.", event->name);
+                        log_debug("%s has been moved away, revalidating.", j);
 
                 h = hashmap_get(m->homes_by_name, n);
                 if (h) {
@@ -487,7 +494,7 @@ static int search_quota(uid_t uid, const char *exclude_quota_path) {
          * comprehensive, but should cover most cases. Note that in an ideal world every user would be
          * registered in NSS and avoid our own UID range, but for all other cases, it's a good idea to be
          * paranoid and check quota if we can. */
-        FOREACH_STRING(where, "/home/", "/tmp/", "/var/", "/var/mail/", "/var/tmp/", "/var/spool/") {
+        FOREACH_STRING(where, get_home_root(), "/tmp/", "/var/", "/var/mail/", "/var/tmp/", "/var/spool/") {
                 struct dqblk req;
                 struct stat st;
 
@@ -914,13 +921,13 @@ int manager_enumerate_images(Manager *m) {
         if (!m->scan_slash_home)
                 return 0;
 
-        d = opendir("/home/");
+        d = opendir(get_home_root());
         if (!d)
                 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
-                                      "Failed to open /home/: %m");
+                                      "Failed to open %s: %m", get_home_root());
 
-        FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read /home/ directory: %m"))
-                (void) manager_assess_image(m, dirfd(d), "/home", de->d_name);
+        FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read %s directory: %m", get_home_root()))
+                (void) manager_assess_image(m, dirfd(d), get_home_root(), de->d_name);
 
         return 0;
 }
index 49533b242293af19fc1eb0bc76ff8f1a438f8e94..ae3fffed02c63ed82b0f4e8092fc58b950ec184c 100644 (file)
@@ -1129,12 +1129,12 @@ static int determine_default_storage(UserStorage *ret) {
         if (r < 0)
                 return log_error_errno(r, "Failed to determine whether we are in a container: %m");
         if (r == 0) {
-                r = path_is_encrypted("/home");
+                r = path_is_encrypted(get_home_root());
                 if (r > 0)
-                        log_info("/home is encrypted, not using '%s' storage, in order to avoid double encryption.", user_storage_to_string(USER_LUKS));
+                        log_info("%s is encrypted, not using '%s' storage, in order to avoid double encryption.", get_home_root(), user_storage_to_string(USER_LUKS));
                 else {
                         if (r < 0)
-                                log_warning_errno(r, "Failed to determine if /home is encrypted, ignoring: %m");
+                                log_warning_errno(r, "Failed to determine if %s is encrypted, ignoring: %m", get_home_root());
 
                         r = dlopen_cryptsetup();
                         if (r < 0)
@@ -1148,14 +1148,14 @@ static int determine_default_storage(UserStorage *ret) {
         } else
                 log_info("Running in container, not using '%s' storage.", user_storage_to_string(USER_LUKS));
 
-        r = path_is_fs_type("/home", BTRFS_SUPER_MAGIC);
+        r = path_is_fs_type(get_home_root(), BTRFS_SUPER_MAGIC);
         if (r < 0)
-                log_warning_errno(r, "Failed to determine file system of /home, ignoring: %m");
+                log_warning_errno(r, "Failed to determine file system of %s, ignoring: %m", get_home_root());
         if (r > 0) {
-                log_info("/home is on btrfs, using '%s' as storage.", user_storage_to_string(USER_SUBVOLUME));
+                log_info("%s is on btrfs, using '%s' as storage.", get_home_root(), user_storage_to_string(USER_SUBVOLUME));
                 *ret = USER_SUBVOLUME;
         } else {
-                log_info("/home is on simple file system, using '%s' as storage.", user_storage_to_string(USER_DIRECTORY));
+                log_info("%s is on simple file system, using '%s' as storage.", get_home_root(), user_storage_to_string(USER_DIRECTORY));
                 *ret = USER_DIRECTORY;
         }
 
index bc0c4171b4f38265a1bf1858e65d19806271d0e1..464f1dbb7a096377f92d2a8e80ad075f8982f59f 100644 (file)
@@ -75,7 +75,7 @@ int user_record_synthesize(
         if (!ip)
                 return -ENOMEM;
 
-        hd = path_join("/home/", user_name);
+        hd = path_join(get_home_root(), user_name);
         if (!hd)
                 return -ENOMEM;
 
index 44f629a910b19f4b0597f29c2cf78e847552ad11..9b2029bfcfb0d214f5afbac9f7201cc3385717f1 100644 (file)
@@ -1408,11 +1408,11 @@ int user_record_build_image_path(UserStorage storage, const char *user_name_and_
                 return 0;
         }
 
-        z = strjoin("/home/", user_name_and_realm, suffix);
+        z = strjoin(get_home_root(), "/", user_name_and_realm, suffix);
         if (!z)
                 return -ENOMEM;
 
-        *ret = z;
+        *ret = path_simplify(z);
         return 1;
 }
 
@@ -1437,7 +1437,7 @@ static int user_record_augment(UserRecord *h, JsonDispatchFlags json_flags) {
                 return 0;
 
         if (!h->home_directory && !h->home_directory_auto) {
-                h->home_directory_auto = path_join("/home/", h->user_name);
+                h->home_directory_auto = path_join(get_home_root(), h->user_name);
                 if (!h->home_directory_auto)
                         return json_log_oom(h->json, json_flags);
         }