cryptsetup: use the new crypt_token_set_external_path() API if available
authorLennart Poettering <lennart@poettering.net>
Tue, 10 Sep 2024 13:40:12 +0000 (15:40 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 10 Sep 2024 17:56:55 +0000 (02:56 +0900)
Let's make use of libcryptsetup's new crypt_token_set_external_path()
API in place of the interposition stuff we have been doing before. Let's
kill it entirely, given that this was a developer feature only anyway
(and guarded by an appropriate ifdef).

Fixes: #30098

meson.build
src/shared/cryptsetup-util.c
src/shared/cryptsetup-util.h

index 80e0047281b3d849bc15f50fb5807e26d2316d66..6d96996acbd9e2f44d2c9a344a91eb06191ba347 100644 (file)
@@ -1288,7 +1288,8 @@ foreach ident : ['crypt_set_metadata_size',
                  'crypt_reencrypt_run',
                  'crypt_set_data_offset',
                  'crypt_set_keyring_to_link',
-                 'crypt_resume_by_volume_key']
+                 'crypt_resume_by_volume_key',
+                 'crypt_token_set_external_path']
         have_ident = have and cc.has_function(
                 ident,
                 prefix : '#include <libcryptsetup.h>',
index 026738b74c2b949a96780bc2c0e037b021393690..46f91934537177f8c398c8e1df97a8002091b163 100644 (file)
@@ -49,6 +49,9 @@ DLSYM_PROTOTYPE(crypt_token_json_set) = NULL;
 #if HAVE_CRYPT_TOKEN_MAX
 DLSYM_PROTOTYPE(crypt_token_max) = NULL;
 #endif
+#if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH
+DLSYM_PROTOTYPE(crypt_token_set_external_path) = NULL;
+#endif
 DLSYM_PROTOTYPE(crypt_token_status) = NULL;
 DLSYM_PROTOTYPE(crypt_volume_key_get) = NULL;
 #if HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE
@@ -66,41 +69,6 @@ DLSYM_PROTOTYPE(crypt_set_data_offset) = NULL;
 DLSYM_PROTOTYPE(crypt_header_restore) = NULL;
 DLSYM_PROTOTYPE(crypt_volume_key_keyring) = NULL;
 
-/* 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 BUILD_MODE_DEVELOPER && defined(__has_attribute) && __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
-
 static void cryptsetup_log_glue(int level, const char *msg, void *usrptr) {
 
         switch (level) {
@@ -295,6 +263,9 @@ int dlopen_cryptsetup(void) {
                         DLSYM_ARG(crypt_token_json_set),
 #if HAVE_CRYPT_TOKEN_MAX
                         DLSYM_ARG(crypt_token_max),
+#endif
+#if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH
+                        DLSYM_ARG(crypt_token_set_external_path),
 #endif
                         DLSYM_ARG(crypt_token_status),
                         DLSYM_ARG(crypt_volume_key_get),
@@ -321,6 +292,18 @@ int dlopen_cryptsetup(void) {
          * other code loaded into this process also changes the global log functions of libcryptsetup, who
          * knows? And if so, we still want our own objects to log via our own infra, at the very least.) */
         cryptsetup_enable_logging(NULL);
+
+        const char *e = secure_getenv("SYSTEMD_CRYPTSETUP_TOKEN_PATH");
+        if (e) {
+#if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH
+                r = sym_crypt_token_set_external_path(e);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to set the libcryptsetup external token path to '%s', ignoring: %m", e);
+#else
+                log_debug("libcryptsetup version does not support setting the external token path, not setting it to '%s'.", e);
+#endif
+        }
+
         return 1;
 #else
         return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "cryptsetup support is not compiled in.");
index 86ac022f3031ef2b6c9dee312682508de2b2405a..ea3baf9675b0df4c6e74c9f8a21e059799a7ba08 100644 (file)
@@ -68,6 +68,9 @@ static inline int crypt_token_max(_unused_ const char *type) {
 }
 #define sym_crypt_token_max(type) crypt_token_max(type)
 #endif
+#if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH
+extern DLSYM_PROTOTYPE(crypt_token_set_external_path);
+#endif
 extern DLSYM_PROTOTYPE(crypt_token_status);
 extern DLSYM_PROTOTYPE(crypt_volume_key_get);
 #if HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE