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.
This commit is contained in:
Lennart Poettering 2023-10-30 22:26:09 +01:00 committed by Luca Boccassi
parent 2bdd7a8ac9
commit 0631eac96d
2 changed files with 42 additions and 0 deletions

View 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`:

View 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) {