1
0
mirror of https://github.com/systemd/systemd synced 2026-04-24 16:04:51 +02:00

Compare commits

..

16 Commits

Author SHA1 Message Date
Lennart Poettering
d6d450074f
Merge pull request #22919 from poettering/cryptsetup-tweaks
various minor tweaks to cryptsetup/veritysetup/integritysetup
2022-03-31 16:50:37 +02:00
Antonio Alvarez Feijoo
49be03838d cryptsetup: fall back to traditional unlocking if any TPM2 operation fails
If any TPM2 operation fails, the boot process should continue and
prompt for a text password (if configured to do so).

Fixes #22870
2022-03-31 14:58:21 +01:00
Lennart Poettering
9e83d3e45f update TODO 2022-03-31 14:39:55 +02:00
Martin Liska
0bd292567a Support -D_FORTIFY_SOURCE=3 by using __builtin_dynamic_object_size.
As explained in the issue, -D_FORTIFY_SOURCE=3 requires usage
of __builtin_dynamic_object_size in MALLOC_SIZEOF_SAFE macro.

Fixes: #22801
2022-03-31 21:13:34 +09:00
Franck Bui
f887eab1da meson: build kernel-install man page when necessary 2022-03-31 21:12:05 +09:00
Lennart Poettering
e2bc5194af integritysetup: also validate volume name
Exactly like for veritysetup/cryptsetup
2022-03-31 11:44:46 +02:00
Lennart Poettering
752d859442 integritysetup: also port to mangle_none()
Let's make the tool work more like veritysetup/cryptsetup in this regard
too.
2022-03-31 11:44:46 +02:00
Lennart Poettering
2b4b030044 integritysetup: log when attempted to detach already detached volume
To make the tool behave more like cryptsetup/veritysetup
2022-03-31 11:44:46 +02:00
Lennart Poettering
042fcbbf7e integritysetup: rename action → verb, to match other code 2022-03-31 11:44:46 +02:00
Lennart Poettering
542bb9be7c tree-wide: unify some code that looks for --help in the command line 2022-03-31 11:44:46 +02:00
Lennart Poettering
9959d78280 veritysetup: do some superficial checking on volume name
cryptsetup does this too, so let's better be safe here, too.
2022-03-31 11:44:46 +02:00
Lennart Poettering
bb3ff7a996 veritysetup: mangle option strings like in cryptsetup 2022-03-31 11:44:46 +02:00
Lennart Poettering
49a4a81dd7 veritysetup: give command line parameters proper names
Accessing the various arguments always through argv[] is nasty, since
it's not obvious what we are talking about here. Let's give things nice
names.

We did the same in cryptsetup a while back.
2022-03-31 11:24:10 +02:00
Lennart Poettering
2e4aae981e cryptsetup: adjust some log levels
Let's upgrade log levels of some noteworthy messages from LOG_DEBUG to
LOG_NOTICE. These messages contain information that previous log
messages in the error path didn't say, namely that we'll now fall back
to traditional unlocking.

Note that this leaves similar log messages for cases where
TPM2/PKCS#11/FIDO2 support is disabled at build at LOG_DEBUG, since in
that case nothing really failed, we just systematically can't do
TPM2/PKCS#11/FIDO2 and hence it is pointless and not actionable for
users to do anything about it...
2022-03-31 11:24:07 +02:00
Lennart Poettering
2fabbad898 cryptsetup: add helper for mangling "none" option strings
let's unify some code here, and let's do so in cryptsetup-util.h so that
we can later reuse this in integritysetup/veritysetup
2022-03-31 11:24:01 +02:00
Lennart Poettering
dcbc38c916 cryptsetup: rename functions that try to do FIDO2/TPM2/PKCS#11 via cryptsetup plugins to say so
The are so many different flavours of functions that attach volumes,
hence say explicitly that these are about libcryptsetup plugins, and
nothing else.

Just some renaming, no code changes beyond that.
2022-03-31 11:23:16 +02:00
14 changed files with 148 additions and 67 deletions

5
TODO
View File

@ -78,6 +78,11 @@ Janitorial Clean-ups:
Features: Features:
* support uefi/http boots with sd-boot: instead of looking for dropin files in
/loader/entries/ dir, look for a file /loader/entries/SHA256SUMS and use that
as directory manifest. The file would be a standard directory listing as
generated by GNU sha256sums.
* initialize machine ID from systemd credential picked up from the ESP via * initialize machine ID from systemd credential picked up from the ESP via
sd-stub, so that machine ID is stable even on systems where unified kernels sd-stub, so that machine ID is stable even on systems where unified kernels
are used, and hence kernel cmdline cannot be modified locally are used, and hence kernel cmdline cannot be modified locally

View File

@ -30,7 +30,7 @@ manpages = [
['journalctl', '1', [], ''], ['journalctl', '1', [], ''],
['journald.conf', '5', ['journald.conf.d', 'journald@.conf'], ''], ['journald.conf', '5', ['journald.conf.d', 'journald@.conf'], ''],
['kernel-command-line', '7', [], ''], ['kernel-command-line', '7', [], ''],
['kernel-install', '8', [], ''], ['kernel-install', '8', [], 'ENABLE_KERNEL_INSTALL'],
['libudev', '3', [], ''], ['libudev', '3', [], ''],
['loader.conf', '5', [], 'HAVE_GNU_EFI'], ['loader.conf', '5', [], 'HAVE_GNU_EFI'],
['locale.conf', '5', [], ''], ['locale.conf', '5', [], ''],

View File

@ -1675,6 +1675,9 @@ else
endif endif
conf.set10('ENABLE_IMPORTD', have) conf.set10('ENABLE_IMPORTD', have)
want_kernel_install = get_option('kernel-install')
conf.set10('ENABLE_KERNEL_INSTALL', want_kernel_install)
want_homed = get_option('homed') want_homed = get_option('homed')
if want_homed != 'false' if want_homed != 'false'
have = (conf.get('HAVE_OPENSSL') == 1 and have = (conf.get('HAVE_OPENSSL') == 1 and
@ -4143,7 +4146,7 @@ foreach tuple : [
['hwdb'], ['hwdb'],
['importd'], ['importd'],
['initrd'], ['initrd'],
['kernel-install', get_option('kernel-install')], ['kernel-install'],
['localed'], ['localed'],
['logind'], ['logind'],
['machined'], ['machined'],

View File

@ -31,7 +31,7 @@ items = [['busctl', ''],
['systemd-path', ''], ['systemd-path', ''],
['systemd-run', ''], ['systemd-run', ''],
['udevadm', ''], ['udevadm', ''],
['kernel-install', ''], ['kernel-install', 'ENABLE_KERNEL_INSTALL'],
['bootctl', 'HAVE_GNU_EFI'], ['bootctl', 'HAVE_GNU_EFI'],
['coredumpctl', 'ENABLE_COREDUMP'], ['coredumpctl', 'ENABLE_COREDUMP'],
['homectl', 'ENABLE_HOMED'], ['homectl', 'ENABLE_HOMED'],

View File

@ -22,7 +22,7 @@ items = [['_busctl', ''],
['_systemd-path', ''], ['_systemd-path', ''],
['_systemd-run', ''], ['_systemd-run', ''],
['_udevadm', ''], ['_udevadm', ''],
['_kernel-install', ''], ['_kernel-install', 'ENABLE_KERNEL_INSTALL'],
['_sd_hosts_or_user_at_host', ''], ['_sd_hosts_or_user_at_host', ''],
['_sd_outputmodes', ''], ['_sd_outputmodes', ''],
['_sd_unit_files', ''], ['_sd_unit_files', ''],

View File

@ -14,10 +14,11 @@
#include "mkdir.h" #include "mkdir.h"
#include "parse-util.h" #include "parse-util.h"
#include "pretty-print.h" #include "pretty-print.h"
#include "terminal-util.h" #include "process-util.h"
#include "reboot-util.h" #include "reboot-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "terminal-util.h"
#include "util.h" #include "util.h"
static int help(void) { static int help(void) {
@ -368,7 +369,7 @@ static int run(int argc, char *argv[]) {
log_setup(); log_setup();
if (strv_contains(strv_skip(argv, 1), "--help")) if (argv_looks_like_help(argc, argv))
return help(); return help();
if (argc != 3) if (argc != 3)

View File

@ -174,13 +174,23 @@ void* greedy_realloc0(void **p, size_t need, size_t size);
* is compatible with _FORTIFY_SOURCES. If _FORTIFY_SOURCES is used many memory operations will take the * is compatible with _FORTIFY_SOURCES. If _FORTIFY_SOURCES is used many memory operations will take the
* object size as returned by __builtin_object_size() into account. Hence, let's return the smaller size of * object size as returned by __builtin_object_size() into account. Hence, let's return the smaller size of
* malloc_usable_size() and __builtin_object_size() here, so that we definitely operate in safe territory by * malloc_usable_size() and __builtin_object_size() here, so that we definitely operate in safe territory by
* both the compiler's and libc's standards. Note that __builtin_object_size() evaluates to SIZE_MAX if the * both the compiler's and libc's standards. Note that _FORTIFY_SOURCES=3 handles also dynamically allocated
* size cannot be determined, hence the MIN() expression should be safe with dynamically sized memory, * objects and thus it's safer using __builtin_dynamic_object_size if _FORTIFY_SOURCES=3 is used (#22801).
* too. Moreover, when NULL is passed malloc_usable_size() is documented to return zero, and * Moreover, when NULL is passed malloc_usable_size() is documented to return zero, and
* __builtin_object_size() returns SIZE_MAX too, hence we also return a sensible value of 0 in this corner * __builtin_object_size() returns SIZE_MAX too, hence we also return a sensible value of 0 in this corner
* case. */ * case. */
#if defined __has_builtin
# if __has_builtin(__builtin_dynamic_object_size)
# define MALLOC_SIZEOF_SAFE(x) \
MIN(malloc_usable_size(x), __builtin_dynamic_object_size(x, 0))
# endif
#endif
#ifndef MALLOC_SIZEOF_SAFE
#define MALLOC_SIZEOF_SAFE(x) \ #define MALLOC_SIZEOF_SAFE(x) \
MIN(malloc_usable_size(x), __builtin_object_size(x, 0)) MIN(malloc_usable_size(x), __builtin_object_size(x, 0))
#endif
/* Inspired by ELEMENTSOF() but operates on malloc()'ed memory areas: typesafely returns the number of items /* Inspired by ELEMENTSOF() but operates on malloc()'ed memory areas: typesafely returns the number of items
* that fit into the specified memory block */ * that fit into the specified memory block */

View File

@ -1615,6 +1615,30 @@ _noreturn_ void freeze(void) {
pause(); pause();
} }
bool argv_looks_like_help(int argc, char **argv) {
char **l;
/* Scans the command line for indications the user asks for help. This is supposed to be called by
* tools that do not implement getopt() style command line parsing because they are not primarily
* user-facing. Detects four ways of asking for help:
*
* 1. Passing zero arguments
* 2. Passing "help" as first argument
* 3. Passing --help as any argument
* 4. Passing -h as any argument
*/
if (argc <= 1)
return true;
if (streq_ptr(argv[1], "help"))
return true;
l = strv_skip(argv, 1);
return strv_contains(l, "--help") ||
strv_contains(l, "-h");
}
static const char *const sigchld_code_table[] = { static const char *const sigchld_code_table[] = {
[CLD_EXITED] = "exited", [CLD_EXITED] = "exited",

View File

@ -191,3 +191,5 @@ int setpriority_closest(int priority);
bool invoked_as(char *argv[], const char *token); bool invoked_as(char *argv[], const char *token);
_noreturn_ void freeze(void); _noreturn_ void freeze(void);
bool argv_looks_like_help(int argc, char **argv);

View File

@ -34,6 +34,7 @@
#include "path-util.h" #include "path-util.h"
#include "pkcs11-util.h" #include "pkcs11-util.h"
#include "pretty-print.h" #include "pretty-print.h"
#include "process-util.h"
#include "random-util.h" #include "random-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
@ -850,7 +851,7 @@ static int acquire_pins_from_env_variable(char ***ret_pins) {
} }
#endif #endif
static int attach_luks2_by_fido2( static int attach_luks2_by_fido2_via_plugin(
struct crypt_device *cd, struct crypt_device *cd,
const char *name, const char *name,
usec_t until, usec_t until,
@ -980,7 +981,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
for (;;) { for (;;) {
if (use_libcryptsetup_plugin && !arg_fido2_cid) { if (use_libcryptsetup_plugin && !arg_fido2_cid) {
r = attach_luks2_by_fido2(cd, name, until, arg_headless, arg_fido2_device, flags); r = attach_luks2_by_fido2_via_plugin(cd, name, until, arg_headless, arg_fido2_device, flags);
if (IN_SET(r, -ENOTUNIQ, -ENXIO, -ENOENT)) if (IN_SET(r, -ENOTUNIQ, -ENXIO, -ENOENT))
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
"Automatic FIDO2 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking."); "Automatic FIDO2 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
@ -1053,7 +1054,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
return 0; return 0;
} }
static int attach_luks2_by_pkcs11( static int attach_luks2_by_pkcs11_via_plugin(
struct crypt_device *cd, struct crypt_device *cd,
const char *name, const char *name,
const char *friendly_name, const char *friendly_name,
@ -1133,7 +1134,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
for (;;) { for (;;) {
if (use_libcryptsetup_plugin && arg_pkcs11_uri_auto) if (use_libcryptsetup_plugin && arg_pkcs11_uri_auto)
r = attach_luks2_by_pkcs11(cd, name, friendly, until, arg_headless, flags); r = attach_luks2_by_pkcs11_via_plugin(cd, name, friendly, until, arg_headless, flags);
else { else {
r = decrypt_pkcs11_key( r = decrypt_pkcs11_key(
name, name,
@ -1246,7 +1247,7 @@ static int make_tpm2_device_monitor(
return 0; return 0;
} }
static int attach_luks2_by_tpm2( static int attach_luks2_by_tpm2_via_plugin(
struct crypt_device *cd, struct crypt_device *cd,
const char *name, const char *name,
uint32_t flags) { uint32_t flags) {
@ -1322,23 +1323,28 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
return log_error_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking."); return log_error_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking.");
if (ERRNO_IS_NOT_SUPPORTED(r)) /* TPM2 support not compiled in? */ if (ERRNO_IS_NOT_SUPPORTED(r)) /* TPM2 support not compiled in? */
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 support not available, falling back to traditional unlocking."); return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 support not available, falling back to traditional unlocking.");
if (r != -EAGAIN) /* EAGAIN means: no tpm2 chip found */ /* EAGAIN means: no tpm2 chip found */
return r; if (r != -EAGAIN) {
log_notice_errno(r, "TPM2 operation failed, falling back to traditional unlocking: %m");
return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
}
} else { } else {
r = attach_luks2_by_tpm2(cd, name, flags); r = attach_luks2_by_tpm2_via_plugin(cd, name, flags);
/* EAGAIN means: no tpm2 chip found /* EAGAIN means: no tpm2 chip found
* EOPNOTSUPP means: no libcryptsetup plugins support */ * EOPNOTSUPP means: no libcryptsetup plugins support */
if (r == -ENXIO) if (r == -ENXIO)
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN),
"No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking."); "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking.");
if (r == -ENOENT) if (r == -ENOENT)
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
"No TPM2 metadata enrolled in LUKS2 header or TPM2 support not available, falling back to traditional unlocking."); "No TPM2 metadata enrolled in LUKS2 header or TPM2 support not available, falling back to traditional unlocking.");
if (!IN_SET(r, -EOPNOTSUPP, -EAGAIN)) if (!IN_SET(r, -EOPNOTSUPP, -EAGAIN)) {
return r; log_notice_errno(r, "TPM2 operation failed, falling back to traditional unlocking: %m");
return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
}
} }
if (r == -EOPNOTSUPP) { if (r == -EOPNOTSUPP) { /* Plugin not available, let's process TPM2 stuff right here instead */
_cleanup_free_ void *blob = NULL, *policy_hash = NULL; _cleanup_free_ void *blob = NULL, *policy_hash = NULL;
size_t blob_size, policy_hash_size; size_t blob_size, policy_hash_size;
bool found_some = false; bool found_some = false;
@ -1367,10 +1373,11 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
&tpm2_flags); &tpm2_flags);
if (r == -ENXIO) if (r == -ENXIO)
/* No further TPM2 tokens found in the LUKS2 header. */ /* No further TPM2 tokens found in the LUKS2 header. */
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), return log_full_errno(found_some ? LOG_NOTICE : LOG_DEBUG,
found_some SYNTHETIC_ERRNO(EAGAIN),
? "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking." found_some
: "No TPM2 metadata enrolled in LUKS2 header, falling back to traditional unlocking."); ? "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking."
: "No TPM2 metadata enrolled in LUKS2 header, falling back to traditional unlocking.");
if (ERRNO_IS_NOT_SUPPORTED(r)) /* TPM2 support not compiled in? */ if (ERRNO_IS_NOT_SUPPORTED(r)) /* TPM2 support not compiled in? */
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 support not available, falling back to traditional unlocking."); return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 support not available, falling back to traditional unlocking.");
if (r < 0) if (r < 0)
@ -1393,7 +1400,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
arg_ask_password_flags, arg_ask_password_flags,
&decrypted_key, &decrypted_key_size); &decrypted_key, &decrypted_key_size);
if (IN_SET(r, -EACCES, -ENOLCK)) if (IN_SET(r, -EACCES, -ENOLCK))
return log_error_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking."); return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking.");
if (r != -EPERM) if (r != -EPERM)
break; break;
@ -1402,8 +1409,11 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
if (r >= 0) if (r >= 0)
break; break;
if (r != -EAGAIN) /* EAGAIN means: no tpm2 chip found */ /* EAGAIN means: no tpm2 chip found */
return r; if (r != -EAGAIN) {
log_notice_errno(r, "TPM2 operation failed, falling back to traditional unlocking: %m");
return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
}
} }
if (!monitor) { if (!monitor) {
@ -1718,7 +1728,7 @@ static int run(int argc, char *argv[]) {
const char *verb; const char *verb;
int r; int r;
if (argc <= 1) if (argv_looks_like_help(argc, argv))
return help(); return help();
if (argc < 3) if (argc < 3)
@ -1750,8 +1760,8 @@ static int run(int argc, char *argv[]) {
volume = argv[2]; volume = argv[2];
source = argv[3]; source = argv[3];
key_file = argc >= 5 && !STR_IN_SET(argv[4], "", "-", "none") ? argv[4] : NULL; key_file = mangle_none(argc >= 5 ? argv[4] : NULL);
options = argc >= 6 && !STR_IN_SET(argv[5], "", "-", "none") ? argv[5] : NULL; options = mangle_none(argc >= 6 ? argv[5] : NULL);
if (!filename_is_valid(volume)) if (!filename_is_valid(volume))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);

View File

@ -12,9 +12,10 @@
#include "log.h" #include "log.h"
#include "main-func.h" #include "main-func.h"
#include "memory-util.h" #include "memory-util.h"
#include "path-util.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h" #include "pretty-print.h"
#include "process-util.h"
#include "string-util.h" #include "string-util.h"
#include "terminal-util.h" #include "terminal-util.h"
@ -87,19 +88,16 @@ static const char *integrity_algorithm_select(const void *key_file_buf) {
static int run(int argc, char *argv[]) { static int run(int argc, char *argv[]) {
_cleanup_(crypt_freep) struct crypt_device *cd = NULL; _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
char *verb, *volume;
int r; int r;
char *action, *volume;
if (argc <= 1 || if (argv_looks_like_help(argc, argv))
strv_contains(strv_skip(argv, 1), "--help") ||
strv_contains(strv_skip(argv, 1), "-h") ||
streq(argv[1], "help"))
return help(); return help();
if (argc < 3) if (argc < 3)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires at least two arguments."); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires at least two arguments.");
action = argv[1]; verb = argv[1];
volume = argv[2]; volume = argv[2];
log_setup(); log_setup();
@ -108,7 +106,7 @@ static int run(int argc, char *argv[]) {
umask(0022); umask(0022);
if (streq(action, "attach")) { if (streq(verb, "attach")) {
/* attach name device optional_key_file optional_options */ /* attach name device optional_key_file optional_options */
crypt_status_info status; crypt_status_info status;
@ -123,8 +121,11 @@ static int run(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach has a maximum of five arguments."); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach has a maximum of five arguments.");
device = argv[3]; device = argv[3];
key_file = (argc > 4) ? empty_or_dash_to_null(argv[4]) : NULL; key_file = mangle_none(argc > 4 ? argv[4] : NULL);
options = (argc > 5) ? empty_or_dash_to_null(argv[5]) : NULL; options = mangle_none(argc > 5 ? argv[5] : NULL);
if (!filename_is_valid(volume))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
if (key_file) { if (key_file) {
r = load_key_file(key_file, &key_buf, &key_buf_size); r = load_key_file(key_file, &key_buf, &key_buf_size);
@ -171,14 +172,19 @@ static int run(int argc, char *argv[]) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to set up integrity device: %m"); return log_error_errno(r, "Failed to set up integrity device: %m");
} else if (streq(action, "detach")) { } else if (streq(verb, "detach")) {
if (argc > 3) if (argc > 3)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "detach has a maximum of two arguments."); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "detach has a maximum of two arguments.");
if (!filename_is_valid(volume))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
r = crypt_init_by_name(&cd, volume); r = crypt_init_by_name(&cd, volume);
if (r == -ENODEV) if (r == -ENODEV) {
log_info("Volume %s already inactive.", volume);
return 0; return 0;
}
if (r < 0) if (r < 0)
return log_error_errno(r, "crypt_init_by_name() failed: %m"); return log_error_errno(r, "crypt_init_by_name() failed: %m");
@ -189,7 +195,7 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to deactivate: %m"); return log_error_errno(r, "Failed to deactivate: %m");
} else } else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb %s.", action); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb %s.", verb);
return 0; return 0;
} }

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
want_kernel_install = get_option('kernel-install')
if want_kernel_install if want_kernel_install
install_data('kernel-install', install_data('kernel-install',
install_mode : 'rwxr-xr-x', install_mode : 'rwxr-xr-x',

View File

@ -86,3 +86,8 @@ static inline void sym_crypt_free(struct crypt_device* cd) {}
static inline void sym_crypt_freep(struct crypt_device** cd) {} static inline void sym_crypt_freep(struct crypt_device** cd) {}
#endif #endif
static inline const char *mangle_none(const char *s) {
/* A helper that turns cryptsetup/integritysetup/veritysetup "options" strings into NULL if they are effectively empty */
return isempty(s) || STR_IN_SET(s, "-", "none") ? NULL : s;
}

View File

@ -12,6 +12,7 @@
#include "main-func.h" #include "main-func.h"
#include "path-util.h" #include "path-util.h"
#include "pretty-print.h" #include "pretty-print.h"
#include "process-util.h"
#include "string-util.h" #include "string-util.h"
#include "terminal-util.h" #include "terminal-util.h"
@ -111,12 +112,10 @@ static int parse_options(const char *options) {
static int run(int argc, char *argv[]) { static int run(int argc, char *argv[]) {
_cleanup_(crypt_freep) struct crypt_device *cd = NULL; _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
const char *verb;
int r; int r;
if (argc <= 1 || if (argv_looks_like_help(argc, argv))
strv_contains(strv_skip(argv, 1), "--help") ||
strv_contains(strv_skip(argv, 1), "-h") ||
streq(argv[1], "help"))
return help(); return help();
if (argc < 3) if (argc < 3)
@ -128,7 +127,10 @@ static int run(int argc, char *argv[]) {
umask(0022); umask(0022);
if (streq(argv[1], "attach")) { verb = argv[1];
if (streq(verb, "attach")) {
const char *volume, *data_device, *verity_device, *root_hash, *options;
_cleanup_free_ void *m = NULL; _cleanup_free_ void *m = NULL;
crypt_status_info status; crypt_status_info status;
size_t l; size_t l;
@ -136,24 +138,33 @@ static int run(int argc, char *argv[]) {
if (argc < 6) if (argc < 6)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least four arguments."); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least four arguments.");
r = unhexmem(argv[5], strlen(argv[5]), &m, &l); volume = argv[2];
data_device = argv[3];
verity_device = argv[4];
root_hash = argv[5];
options = mangle_none(argc > 6 ? argv[6] : NULL);
if (!filename_is_valid(volume))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
r = unhexmem(root_hash, SIZE_MAX, &m, &l);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to parse root hash: %m"); return log_error_errno(r, "Failed to parse root hash: %m");
r = crypt_init(&cd, argv[4]); r = crypt_init(&cd, verity_device);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to open verity device %s: %m", argv[4]); return log_error_errno(r, "Failed to open verity device %s: %m", verity_device);
cryptsetup_enable_logging(cd); cryptsetup_enable_logging(cd);
status = crypt_status(cd, argv[2]); status = crypt_status(cd, volume);
if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) { if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) {
log_info("Volume %s already active.", argv[2]); log_info("Volume %s already active.", volume);
return 0; return 0;
} }
if (argc > 6) { if (options) {
r = parse_options(argv[6]); r = parse_options(options);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to parse options: %m"); return log_error_errno(r, "Failed to parse options: %m");
} }
@ -162,7 +173,7 @@ static int run(int argc, char *argv[]) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to load verity superblock: %m"); return log_error_errno(r, "Failed to load verity superblock: %m");
r = crypt_set_data_device(cd, argv[3]); r = crypt_set_data_device(cd, data_device);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to configure data device: %m"); return log_error_errno(r, "Failed to configure data device: %m");
@ -186,20 +197,26 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to read root hash signature: %m"); return log_error_errno(r, "Failed to read root hash signature: %m");
} }
r = crypt_activate_by_signed_key(cd, argv[2], m, l, hash_sig, hash_sig_size, arg_activate_flags); r = crypt_activate_by_signed_key(cd, volume, m, l, hash_sig, hash_sig_size, arg_activate_flags);
#else #else
assert_not_reached(); assert_not_reached();
#endif #endif
} else } else
r = crypt_activate_by_volume_key(cd, argv[2], m, l, arg_activate_flags); r = crypt_activate_by_volume_key(cd, volume, m, l, arg_activate_flags);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to set up verity device: %m"); return log_error_errno(r, "Failed to set up verity device: %m");
} else if (streq(argv[1], "detach")) { } else if (streq(verb, "detach")) {
const char *volume;
r = crypt_init_by_name(&cd, argv[2]); volume = argv[2];
if (!filename_is_valid(volume))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
r = crypt_init_by_name(&cd, volume);
if (r == -ENODEV) { if (r == -ENODEV) {
log_info("Volume %s already inactive.", argv[2]); log_info("Volume %s already inactive.", volume);
return 0; return 0;
} }
if (r < 0) if (r < 0)
@ -207,12 +224,12 @@ static int run(int argc, char *argv[]) {
cryptsetup_enable_logging(cd); cryptsetup_enable_logging(cd);
r = crypt_deactivate(cd, argv[2]); r = crypt_deactivate(cd, volume);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to deactivate: %m"); return log_error_errno(r, "Failed to deactivate: %m");
} else } else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb %s.", argv[1]); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb %s.", verb);
return 0; return 0;
} }