]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
crytsetup: allow overriding the token .so library path via an env var
authorLennart Poettering <lennart@poettering.net>
Mon, 30 Oct 2023 21:26:09 +0000 (22:26 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Thu, 2 Nov 2023 18:18:00 +0000 (18:18 +0000)
I tried to get something similar upstream:

https://gitlab.com/cryptsetup/cryptsetup/-/issues/846

But no luck, it was suggested I use ELF interposition instead. Hence,
let's do so (but not via ugly LD_PRELOAD, but simply by overriding the
relevant symbol natively in our own code).

This makes debugging tokens a ton easier.

docs/ENVIRONMENT.md
src/shared/cryptsetup-util.c

index 5747c103e2b0c149924d70af36567f9ad8107b96..3a42774212e0466e867b94b3878aedbd5ffd1287 100644 (file)
@@ -465,6 +465,11 @@ disk images with `--image=` or similar:
   activating via FIDO2, PKCS#11, TPM2, i.e. mechanisms natively supported by
   `systemd-cryptsetup`. Defaults to enabled.
 
+* `$SYSTEMD_CRYPTSETUP_TOKEN_PATH` – takes a path to a directory in the file
+  system. If specified overrides where libcryptsetup will look for token
+  modules (.so). This is useful for debugging token modules: set this
+  environment variable to the build directory and you are set.
+
 Various tools that read passwords from the TTY, such as `systemd-cryptenroll`
 and `homectl`:
 
index c6614d35796e91c67c745c6e4cf0abaa6fd62a2c..19241015fb1eb815cb30275919e4dfc02a29ca81 100644 (file)
@@ -62,6 +62,43 @@ int (*sym_crypt_set_data_offset)(struct crypt_device *cd, uint64_t data_offset);
 int (*sym_crypt_header_restore)(struct crypt_device *cd, const char *requested_type, const char *backup_file);
 int (*sym_crypt_volume_key_keyring)(struct crypt_device *cd, int enable);
 
+/* Unfortunately libcryptsetup provides neither an environment variable to redirect where to look for token
+ * modules, nor does it have an API to change the token lookup path at runtime. The maintainers suggest using
+ * ELF interposition instead (see https://gitlab.com/cryptsetup/cryptsetup/-/issues/846). Hence let's do
+ * that: let's interpose libcryptsetup's crypt_token_external_path() function with our own, that *does*
+ * honour an environment variable where to look for tokens. This is tremendously useful for debugging
+ * libcryptsetup tokens: set the environment variable to your build dir and you can easily test token modules
+ * without jumping through various hoops. */
+
+/* Do this only on new enough compilers that actually support the "symver" attribute. Given this is a debug
+ * feature, let's simply not bother on older compilers */
+#if defined __has_attribute
+#if __has_attribute(symver)
+const char *my_crypt_token_external_path(void); /* prototype for our own implementation */
+
+/* We use the "symver" attribute to mark this implementation as the default implementation, and drop the
+ * SD_SHARED namespace we by default attach to our symbols via a version script. */
+__attribute__((symver("crypt_token_external_path@@")))
+_public_ const char *my_crypt_token_external_path(void) {
+        const char *e;
+
+        e = secure_getenv("SYSTEMD_CRYPTSETUP_TOKEN_PATH");
+        if (e)
+                return e;
+
+        /* Now chain invoke the original implementation. */
+        if (cryptsetup_dl) {
+                typeof(crypt_token_external_path) *func;
+                func = (typeof(crypt_token_external_path)*) dlsym(cryptsetup_dl, "crypt_token_external_path");
+                if (func)
+                        return func();
+        }
+
+        return NULL;
+}
+#endif
+#endif
+
 static void cryptsetup_log_glue(int level, const char *msg, void *usrptr) {
 
         switch (level) {