cryptsetup: load libcryptsetup via dlopen in setup binaries

Convert systemd-cryptsetup, systemd-cryptenroll, systemd-veritysetup
and systemd-integritysetup to go through the existing dlopen wrapper
for libcryptsetup instead of linking the library directly. Each binary
calls dlopen_cryptsetup() at the start of its run() and uses the sym_*
variants for every libcryptsetup entry point.

Extend cryptsetup-util.{h,c} to cover the libcryptsetup symbols that
these binaries use and that the wrapper was missing:
crypt_activate_by_token_pin, crypt_deactivate, crypt_init_data_device,
crypt_keyslot_status, crypt_set_keyring_to_link (conditional on
HAVE_CRYPT_SET_KEYRING_TO_LINK), crypt_status and
crypt_token_external_path.

With no direct callers of crypt_free() left, drop the non-sym
crypt_freep cleanup variant and rename sym_crypt_freep back to
crypt_freep via DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME, matching the
naming convention used by other dlopen wrappers (acl_freep,
xkb_context_unrefp, ...). Update the remaining users in src/shared,
src/repart, src/home and src/growfs to the new name.

The four affected meson targets switch from libcryptsetup to
libcryptsetup_cflags so they no longer record a DT_NEEDED entry for
libcryptsetup.so.12.
This commit is contained in:
Daan De Meyer
2026-04-23 06:42:24 +02:00
committed by Daan De Meyer
parent 4114bf7e70
commit 43dab5ea87
21 changed files with 157 additions and 119 deletions
+4 -4
View File
@@ -54,7 +54,7 @@ int load_volume_key_fido2(
if (passphrase_size < 0)
return log_oom();
r = crypt_volume_key_get(
r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -95,9 +95,9 @@ int enroll_fido2(
assert_se(iovec_is_set(volume_key));
assert_se(device);
assert_se(node = crypt_get_device_name(cd));
assert_se(node = sym_crypt_get_device_name(cd));
un = strempty(crypt_get_uuid(cd));
un = strempty(sym_crypt_get_uuid(cd));
if (salt_file)
r = fido2_read_salt_file(
@@ -140,7 +140,7 @@ int enroll_fido2(
if (r < 0)
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
keyslot = crypt_keyslot_add_by_volume_key(
keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
+2 -2
View File
@@ -26,11 +26,11 @@ int list_enrolled(struct crypt_device *cd) {
assert(cd);
/* First step, find out all currently used slots */
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
for (int slot = 0; slot < slot_max; slot++) {
crypt_keyslot_info status;
status = crypt_keyslot_status(cd, slot);
status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
continue;
+5 -5
View File
@@ -31,7 +31,7 @@ int load_volume_key_password(
if (r < 0)
return log_error_errno(r, "Failed to acquire password from environment: %m");
if (r > 0) {
r = crypt_volume_key_get(
r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -81,7 +81,7 @@ int load_volume_key_password(
r = -EPERM;
STRV_FOREACH(p, passwords) {
r = crypt_volume_key_get(
r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -114,7 +114,7 @@ int enroll_password(
assert(cd);
assert(iovec_is_set(volume_key));
assert_se(node = crypt_get_device_name(cd));
assert_se(node = sym_crypt_get_device_name(cd));
r = getenv_steal_erase("NEWPASSWORD", &new_password);
if (r < 0)
@@ -123,7 +123,7 @@ int enroll_password(
_cleanup_free_ char *disk_path = NULL, *id = NULL;
unsigned i = 5;
assert_se(node = crypt_get_device_name(cd));
assert_se(node = sym_crypt_get_device_name(cd));
(void) suggest_passwords();
@@ -196,7 +196,7 @@ int enroll_password(
else if (r == 0)
log_warning("Specified password does not pass quality checks (%s), proceeding anyway.", error);
keyslot = crypt_keyslot_add_by_volume_key(
keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
+2 -2
View File
@@ -53,7 +53,7 @@ int enroll_pkcs11(struct crypt_device *cd, const struct iovec *volume_key,const
assert_se(iovec_is_set(volume_key));
assert_se(uri);
assert_se(node = crypt_get_device_name(cd));
assert_se(node = sym_crypt_get_device_name(cd));
r = pkcs11_acquire_public_key(
uri,
@@ -80,7 +80,7 @@ int enroll_pkcs11(struct crypt_device *cd, const struct iovec *volume_key,const
if (r < 0)
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
int keyslot = crypt_keyslot_add_by_volume_key(
int keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
+3 -3
View File
@@ -24,7 +24,7 @@ int enroll_recovery(
assert_se(cd);
assert_se(iovec_is_set(volume_key));
assert_se(node = crypt_get_device_name(cd));
assert_se(node = sym_crypt_get_device_name(cd));
r = make_recovery_key(&password);
if (r < 0)
@@ -34,7 +34,7 @@ int enroll_recovery(
if (r < 0)
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
keyslot = crypt_keyslot_add_by_volume_key(
keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
@@ -93,7 +93,7 @@ int enroll_recovery(
return keyslot;
rollback:
q = crypt_keyslot_destroy(cd, keyslot);
q = sym_crypt_keyslot_destroy(cd, keyslot);
if (q < 0)
log_debug_errno(q, "Unable to remove key slot we just added again, can't rollback, sorry: %m");
+3 -3
View File
@@ -272,7 +272,7 @@ int load_volume_key_tpm2(
if (passphrase_size < 0)
return log_oom();
r = crypt_volume_key_get(
r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -329,7 +329,7 @@ int enroll_tpm2(struct crypt_device *cd,
assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
assert(ret_slot_to_wipe);
assert_se(node = crypt_get_device_name(cd));
assert_se(node = sym_crypt_get_device_name(cd));
if (use_pin) {
r = get_pin(&pin_str, &flags);
@@ -579,7 +579,7 @@ int enroll_tpm2(struct crypt_device *cd,
if (r < 0)
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
keyslot = crypt_keyslot_add_by_volume_key(
keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
+13 -13
View File
@@ -15,7 +15,7 @@ static int find_all_slots(struct crypt_device *cd, Set *wipe_slots, Set *keep_sl
assert(cd);
assert(wipe_slots);
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
/* Finds all currently assigned slots, and adds them to 'wipe_slots', except if listed already in 'keep_slots' */
@@ -27,7 +27,7 @@ static int find_all_slots(struct crypt_device *cd, Set *wipe_slots, Set *keep_sl
set_contains(wipe_slots, INT_TO_PTR(slot)))
continue;
status = crypt_keyslot_status(cd, slot);
status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
continue;
@@ -44,12 +44,12 @@ static int find_empty_passphrase_slots(struct crypt_device *cd, Set *wipe_slots,
assert(cd);
assert(wipe_slots);
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
/* Finds all slots with an empty passphrase assigned (i.e. "") and adds them to 'wipe_slots', except
* if listed already in 'keep_slots' */
r = crypt_get_volume_key_size(cd);
r = sym_crypt_get_volume_key_size(cd);
if (r <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine LUKS volume key size");
vks = (size_t) r;
@@ -63,7 +63,7 @@ static int find_empty_passphrase_slots(struct crypt_device *cd, Set *wipe_slots,
set_contains(wipe_slots, INT_TO_PTR(slot)))
continue;
status = crypt_keyslot_status(cd, slot);
status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
continue;
@@ -71,7 +71,7 @@ static int find_empty_passphrase_slots(struct crypt_device *cd, Set *wipe_slots,
if (!vk)
return log_oom();
r = crypt_volume_key_get(cd, slot, vk, &vks, "", 0);
r = sym_crypt_volume_key_get(cd, slot, vk, &vks, "", 0);
if (r < 0) {
log_debug_errno(r, "Failed to acquire volume key from slot %i with empty password, ignoring: %m", slot);
continue;
@@ -164,7 +164,7 @@ static int find_slots_by_mask(
if ((by_mask & (1U << ENROLL_PASSWORD)) != 0) {
int slot_max;
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
for (int slot = 0; slot < slot_max; slot++) {
crypt_keyslot_info status;
@@ -177,7 +177,7 @@ static int find_slots_by_mask(
if (set_contains(listed_slots, INT_TO_PTR(slot))) /* This has a token, hence is not a password. */
continue;
status = crypt_keyslot_status(cd, slot);
status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST)) /* Not actually assigned? */
continue;
@@ -273,7 +273,7 @@ static bool slots_remain(struct crypt_device *cd, Set *wipe_slots, Set *keep_slo
int slot_max;
assert(cd);
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
/* Checks if any slots remaining in the LUKS2 header if we remove all slots listed in 'wipe_slots'
* (keeping those listed in 'keep_slots') */
@@ -281,7 +281,7 @@ static bool slots_remain(struct crypt_device *cd, Set *wipe_slots, Set *keep_slo
for (int slot = 0; slot < slot_max; slot++) {
crypt_keyslot_info status;
status = crypt_keyslot_status(cd, slot);
status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
continue;
@@ -338,7 +338,7 @@ int wipe_slots(struct crypt_device *cd,
if (set_put(keep_slots, INT_TO_PTR(except_slot)) < 0)
return log_oom();
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
/* Maintain another set of the slots we intend to wipe */
for (size_t i = 0; i < n_explicit_slots; i++) {
@@ -425,7 +425,7 @@ int wipe_slots(struct crypt_device *cd,
* first.) */
ret = 0;
for (size_t i = n_ordered_slots; i > 0; i--) {
r = crypt_keyslot_destroy(cd, ordered_slots[i - 1]);
r = sym_crypt_keyslot_destroy(cd, ordered_slots[i - 1]);
if (r < 0) {
if (r == -ENOENT)
log_warning_errno(r, "Failed to wipe non-existent slot %i, continuing.", ordered_slots[i - 1]);
@@ -438,7 +438,7 @@ int wipe_slots(struct crypt_device *cd,
}
for (size_t i = n_ordered_tokens; i > 0; i--) {
r = crypt_token_json_set(cd, ordered_tokens[i - 1], NULL);
r = sym_crypt_token_json_set(cd, ordered_tokens[i - 1], NULL);
if (r < 0) {
log_warning_errno(r, "Failed to wipe token %i, continuing: %m", ordered_tokens[i - 1]);
if (ret == 0)
+9 -7
View File
@@ -649,7 +649,7 @@ static int check_for_homed(struct crypt_device *cd) {
/* Politely refuse operating on homed volumes. The enrolled tokens for the user record and the LUKS2
* volume should not get out of sync. */
for (int token = 0; token < crypt_token_max(CRYPT_LUKS2); token++) {
for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
r = cryptsetup_get_token_as_json(cd, token, "systemd-homed", NULL);
if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE))
continue;
@@ -688,7 +688,7 @@ static int load_volume_key_keyfile(
if (r < 0)
return log_error_errno(r, "Reading keyfile %s failed: %m", arg_unlock_keyfile);
r = crypt_volume_key_get(
r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -710,13 +710,13 @@ static int prepare_luks(
assert(ret_cd);
r = crypt_init(&cd, arg_node);
r = sym_crypt_init(&cd, arg_node);
if (r < 0)
return log_error_errno(r, "Failed to allocate libcryptsetup context: %m");
cryptsetup_enable_logging(cd);
r = crypt_load(cd, CRYPT_LUKS2, NULL);
r = sym_crypt_load(cd, CRYPT_LUKS2, NULL);
if (r < 0)
return log_error_errno(r, "Failed to load LUKS2 superblock of %s: %m", arg_node);
@@ -729,7 +729,7 @@ static int prepare_luks(
return 0;
}
r = crypt_get_volume_key_size(cd);
r = sym_crypt_get_volume_key_size(cd);
if (r <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine LUKS volume key size");
@@ -783,11 +783,13 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
r = dlopen_cryptsetup(LOG_ERR);
if (r < 0)
return r;
/* A delicious drop of snake oil */
(void) safe_mlockall(MCL_CURRENT|MCL_FUTURE|MCL_ONFAULT);
cryptsetup_enable_logging(NULL);
if (arg_enroll_type < 0)
r = prepare_luks(&cd, /* ret_volume_key= */ NULL); /* No need to unlock device if we don't need the volume key because we don't need to enroll anything */
else
+1 -1
View File
@@ -21,7 +21,7 @@ executables += [
'public' : true,
'sources' : systemd_cryptenroll_sources,
'dependencies' : [
libcryptsetup,
libcryptsetup_cflags,
libdl,
libfido2_cflags,
libopenssl,