From 0631eac96d1ef455dae710dc5e4f1c1fecbb3c38 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 30 Oct 2023 22:26:09 +0100 Subject: [PATCH] crytsetup: allow overriding the token .so library path via an env var 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 | 5 +++++ src/shared/cryptsetup-util.c | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 5747c103e2b..3a42774212e 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -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`: diff --git a/src/shared/cryptsetup-util.c b/src/shared/cryptsetup-util.c index c6614d35796..19241015fb1 100644 --- a/src/shared/cryptsetup-util.c +++ b/src/shared/cryptsetup-util.c @@ -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) {