]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homed: tweak logic for picking a default storage and file system
authorLennart Poettering <lennart@poettering.net>
Fri, 1 May 2020 17:42:56 +0000 (19:42 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 7 May 2020 21:33:01 +0000 (23:33 +0200)
Let's make the logic a bit smarter: if we detect that /home is
encrypted, let's avoid double encryption and prefer plain
directory/subvolumes instead of our regular luks images.

Also, allow configuration go storage/file system via an env var passed
to homework. In a later commit, let's then change homed to initialize
that env var from a config file setting, when invoking homework.

src/home/homework.c

index fa0531e04019ff7b28660da6fdfe09a70935f171..71e7cfdb499aaa0585e0bda939a7ef4e2d3dd9e9 100644 (file)
@@ -7,6 +7,7 @@
 #include "copy.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "fs-util.h"
 #include "home-util.h"
 #include "homework-cifs.h"
 #include "homework-directory.h"
@@ -862,9 +863,68 @@ static int user_record_compile_effective_passwords(
         return 0;
 }
 
+static int determine_default_storage(UserStorage *ret) {
+        UserStorage storage = _USER_STORAGE_INVALID;
+        const char *e;
+        int r;
+
+        assert(ret);
+
+        /* homed tells us via an environment variable which default storage to use */
+        e = getenv("SYSTEMD_HOME_DEFAULT_STORAGE");
+        if (e) {
+                storage = user_storage_from_string(e);
+                if (storage < 0)
+                        log_warning("$SYSTEMD_HOME_DEFAULT_STORAGE set to invalid storage type, ignoring: %s", e);
+                else {
+                        log_info("Using configured default storage '%s'.", user_storage_to_string(storage));
+                        *ret = storage;
+                        return 0;
+                }
+        }
+
+        /* When neither user nor admin specified the storage type to use, fix it to be LUKS — unless we run
+         * in a container where loopback devices and LUKS/DM are not available. Also, if /home is encrypted
+         * anyway, let's avoid duplicate encryption. Note that we typically default to the assumption of
+         * "classic" storage for most operations. However, if we create a new home, then let's user LUKS if
+         * nothing is specified. */
+
+        r = detect_container();
+        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");
+                if (r < 0)
+                        log_warning_errno(r, "Failed to determine if /home is encrypted, ignoring: %m");
+                if (r <= 0) {
+                        log_info("Using automatic default storage of '%s'.", user_storage_to_string(USER_LUKS));
+                        *ret = USER_LUKS;
+                        return 0;
+                }
+
+                log_info("/home is encrypted, not using '%s' storage, in order to avoid double encryption.", user_storage_to_string(USER_LUKS));
+        } 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);
+        if (r < 0)
+                log_warning_errno(r, "Failed to determine file system of /home, ignoring: %m");
+        if (r > 0) {
+                log_info("/home is on btrfs, using '%s' as storage.", 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));
+                *ret = USER_DIRECTORY;
+        }
+
+        return 0;
+}
+
 static int home_create(UserRecord *h, UserRecord **ret_home) {
         _cleanup_(strv_free_erasep) char **effective_passwords = NULL, **pkcs11_decrypted_passwords = NULL;
         _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
+        UserStorage new_storage = _USER_STORAGE_INVALID;
+        const char *new_fs = NULL;
         int r;
 
         assert(h);
@@ -884,27 +944,18 @@ static int home_create(UserRecord *h, UserRecord **ret_home) {
         if (r != USER_TEST_ABSENT)
                 return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Home directory %s already exists, refusing.", user_record_home_directory(h));
 
-        /* When the user didn't specify the storage type to use, fix it to be LUKS -- unless we run in a
-         * container where loopback devices and LUKS/DM are not available. Note that we typically default to
-         * the assumption of "classic" storage for most operations. However, if we create a new home, then
-         * let's user LUKS if nothing is specified. */
         if (h->storage < 0) {
-                UserStorage new_storage;
-
-                r = detect_container();
+                r = determine_default_storage(&new_storage);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to determine whether we are in a container: %m");
-                if (r > 0) {
-                        new_storage = USER_DIRECTORY;
-
-                        r = path_is_fs_type("/home", BTRFS_SUPER_MAGIC);
-                        if (r < 0)
-                                log_debug_errno(r, "Failed to determine file system of /home, ignoring: %m");
+                        return r;
+        }
 
-                        new_storage = r > 0 ? USER_SUBVOLUME : USER_DIRECTORY;
-                } else
-                        new_storage = USER_LUKS;
+        if ((h->storage == USER_LUKS ||
+             (h->storage < 0 && new_storage == USER_LUKS)) &&
+            !h->file_system_type)
+                new_fs = getenv("SYSTEMD_HOME_DEFAULT_FILE_SYSTEM_TYPE");
 
+        if (new_storage >= 0 || new_fs) {
                 r = user_record_add_binding(
                                 h,
                                 new_storage,
@@ -915,7 +966,7 @@ static int home_create(UserRecord *h, UserRecord **ret_home) {
                                 NULL,
                                 NULL,
                                 UINT64_MAX,
-                                NULL,
+                                new_fs,
                                 NULL,
                                 UID_INVALID,
                                 GID_INVALID);