···11+From 4f95ab1f8110a8ab9d7b0e192731ce467f6e5c26 Mon Sep 17 00:00:00 2001
22+From: =?UTF-8?q?Janne=20He=C3=9F?= <janne@hess.ooo>
33+Date: Sun, 4 Sep 2022 11:15:02 -0600
44+Subject: [PATCH] Allow loading token handlers from the default search path
55+66+Since [1] landed in cryptsetup, token handlers (libcryptsetup-token-*.so)
77+are loaded from a fixed path defined at compile-time. This is
88+problematic with NixOS since it introduces a dependency cycle
99+between cryptsetup and systemd.
1010+1111+This downstream patch [2] allows loading token plugins from the
1212+default library search path. This approach is not accepted upstream [3]
1313+due to security concerns, but the potential attack vectors require
1414+root access and they are sufficiently addressed:
1515+1616+* cryptsetup could be used as a setuid binary (not used in NixOS).
1717+ In this case, LD_LIBRARY_PATH is ignored because of secure-execution
1818+ mode.
1919+* cryptsetup running as root could lead to a malicious token handler
2020+ being loaded through LD_LIBRARY_PATH. However, fixing the path
2121+ doesn't prevent the same malicious .so being loaded through LD_PRELOAD.
2222+2323+[1] https://gitlab.com/cryptsetup/cryptsetup/-/commit/5b9e98f94178d3cd179d9f6e2a0a68c7d9eb6507
2424+[2] https://github.com/NixOS/nixpkgs/issues/167994#issuecomment-1094249369
2525+[3] https://gitlab.com/cryptsetup/cryptsetup/-/issues/733
2626+---
2727+ lib/luks2/luks2_token.c | 4 +---
2828+ 1 file changed, 1 insertion(+), 3 deletions(-)
2929+3030+diff --git a/lib/luks2/luks2_token.c b/lib/luks2/luks2_token.c
3131+index 26467253..6f8329f0 100644
3232+--- a/lib/luks2/luks2_token.c
3333++++ b/lib/luks2/luks2_token.c
3434+@@ -151,12 +151,10 @@ crypt_token_load_external(struct crypt_device *cd, const char *name, struct cryp
3535+3636+ token = &ret->u.v2;
3737+3838+- r = snprintf(buf, sizeof(buf), "%s/libcryptsetup-token-%s.so", crypt_token_external_path(), name);
3939++ r = snprintf(buf, sizeof(buf), "libcryptsetup-token-%s.so", name);
4040+ if (r < 0 || (size_t)r >= sizeof(buf))
4141+ return -EINVAL;
4242+4343+- assert(*buf == '/');
4444+-
4545+ log_dbg(cd, "Trying to load %s.", buf);
4646+4747+ h = dlopen(buf, RTLD_LAZY);
4848+--
4949+2.37.2
5050+
+10-1
pkgs/os-specific/linux/systemd/default.nix
···77, fetchpatch
88, fetchzip
99, buildPackages
1010+, makeBinaryWrapper
1011, ninja
1112, meson
1213, m4
···333334 nativeBuildInputs =
334335 [
335336 pkg-config
337337+ makeBinaryWrapper
336338 gperf
337339 ninja
338340 meson
···668670 preFixup = lib.optionalString withEfi ''
669671 mv $out/lib/systemd/boot/efi $out/dont-strip-me
670672 '';
671671- postFixup = lib.optionalString withEfi ''
673673+674674+ # Wrap in the correct path for LUKS2 tokens.
675675+ postFixup = lib.optionalString withCryptsetup ''
676676+ for f in lib/systemd/systemd-cryptsetup bin/systemd-cryptenroll; do
677677+ # This needs to be in LD_LIBRARY_PATH because rpath on a binary is not propagated to libraries using dlopen, in this case `libcryptsetup.so`
678678+ wrapProgram $out/$f --prefix LD_LIBRARY_PATH : ${placeholder "out"}/lib/cryptsetup
679679+ done
680680+ '' + lib.optionalString withEfi ''
672681 mv $out/dont-strip-me $out/lib/systemd/boot/efi
673682 '';
674683