1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-24 21:34:08 +03:00

Merge pull request #22919 from poettering/cryptsetup-tweaks

various minor tweaks to cryptsetup/veritysetup/integritysetup
This commit is contained in:
Lennart Poettering 2022-03-31 16:50:37 +02:00 committed by GitHub
commit d6d450074f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 52 deletions

View File

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

View File

@ -1615,6 +1615,30 @@ _noreturn_ void freeze(void) {
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[] = {
[CLD_EXITED] = "exited",

View File

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

View File

@ -34,6 +34,7 @@
#include "path-util.h"
#include "pkcs11-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "random-util.h"
#include "string-util.h"
#include "strv.h"
@ -850,7 +851,7 @@ static int acquire_pins_from_env_variable(char ***ret_pins) {
}
#endif
static int attach_luks2_by_fido2(
static int attach_luks2_by_fido2_via_plugin(
struct crypt_device *cd,
const char *name,
usec_t until,
@ -980,7 +981,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
for (;;) {
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))
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
"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;
}
static int attach_luks2_by_pkcs11(
static int attach_luks2_by_pkcs11_via_plugin(
struct crypt_device *cd,
const char *name,
const char *friendly_name,
@ -1133,7 +1134,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
for (;;) {
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 {
r = decrypt_pkcs11_key(
name,
@ -1246,7 +1247,7 @@ static int make_tpm2_device_monitor(
return 0;
}
static int attach_luks2_by_tpm2(
static int attach_luks2_by_tpm2_via_plugin(
struct crypt_device *cd,
const char *name,
uint32_t flags) {
@ -1328,12 +1329,12 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
}
} 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
* EOPNOTSUPP means: no libcryptsetup plugins support */
if (r == -ENXIO)
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
"No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking.");
return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN),
"No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking.");
if (r == -ENOENT)
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
"No TPM2 metadata enrolled in LUKS2 header or TPM2 support not available, falling back to traditional unlocking.");
@ -1343,7 +1344,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
}
}
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;
size_t blob_size, policy_hash_size;
bool found_some = false;
@ -1372,10 +1373,11 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
&tpm2_flags);
if (r == -ENXIO)
/* No further TPM2 tokens found in the LUKS2 header. */
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
found_some
? "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.");
return log_full_errno(found_some ? LOG_NOTICE : LOG_DEBUG,
SYNTHETIC_ERRNO(EAGAIN),
found_some
? "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? */
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 support not available, falling back to traditional unlocking.");
if (r < 0)
@ -1398,7 +1400,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
arg_ask_password_flags,
&decrypted_key, &decrypted_key_size);
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)
break;
@ -1726,7 +1728,7 @@ static int run(int argc, char *argv[]) {
const char *verb;
int r;
if (argc <= 1)
if (argv_looks_like_help(argc, argv))
return help();
if (argc < 3)
@ -1758,8 +1760,8 @@ static int run(int argc, char *argv[]) {
volume = argv[2];
source = argv[3];
key_file = argc >= 5 && !STR_IN_SET(argv[4], "", "-", "none") ? argv[4] : NULL;
options = argc >= 6 && !STR_IN_SET(argv[5], "", "-", "none") ? argv[5] : NULL;
key_file = mangle_none(argc >= 5 ? argv[4] : NULL);
options = mangle_none(argc >= 6 ? argv[5] : NULL);
if (!filename_is_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 "main-func.h"
#include "memory-util.h"
#include "path-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "string-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[]) {
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
char *verb, *volume;
int r;
char *action, *volume;
if (argc <= 1 ||
strv_contains(strv_skip(argv, 1), "--help") ||
strv_contains(strv_skip(argv, 1), "-h") ||
streq(argv[1], "help"))
if (argv_looks_like_help(argc, argv))
return help();
if (argc < 3)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires at least two arguments.");
action = argv[1];
verb = argv[1];
volume = argv[2];
log_setup();
@ -108,7 +106,7 @@ static int run(int argc, char *argv[]) {
umask(0022);
if (streq(action, "attach")) {
if (streq(verb, "attach")) {
/* attach name device optional_key_file optional_options */
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.");
device = argv[3];
key_file = (argc > 4) ? empty_or_dash_to_null(argv[4]) : NULL;
options = (argc > 5) ? empty_or_dash_to_null(argv[5]) : NULL;
key_file = mangle_none(argc > 4 ? argv[4] : 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) {
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)
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)
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);
if (r == -ENODEV)
if (r == -ENODEV) {
log_info("Volume %s already inactive.", volume);
return 0;
}
if (r < 0)
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");
} 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;
}

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) {}
#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 "path-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "string-util.h"
#include "terminal-util.h"
@ -111,12 +112,10 @@ static int parse_options(const char *options) {
static int run(int argc, char *argv[]) {
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
const char *verb;
int r;
if (argc <= 1 ||
strv_contains(strv_skip(argv, 1), "--help") ||
strv_contains(strv_skip(argv, 1), "-h") ||
streq(argv[1], "help"))
if (argv_looks_like_help(argc, argv))
return help();
if (argc < 3)
@ -128,7 +127,10 @@ static int run(int argc, char *argv[]) {
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;
crypt_status_info status;
size_t l;
@ -136,24 +138,33 @@ static int run(int argc, char *argv[]) {
if (argc < 6)
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)
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)
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);
status = crypt_status(cd, argv[2]);
status = crypt_status(cd, volume);
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;
}
if (argc > 6) {
r = parse_options(argv[6]);
if (options) {
r = parse_options(options);
if (r < 0)
return log_error_errno(r, "Failed to parse options: %m");
}
@ -162,7 +173,7 @@ static int run(int argc, char *argv[]) {
if (r < 0)
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)
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");
}
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
assert_not_reached();
#endif
} 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)
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) {
log_info("Volume %s already inactive.", argv[2]);
log_info("Volume %s already inactive.", volume);
return 0;
}
if (r < 0)
@ -207,12 +224,12 @@ static int run(int argc, char *argv[]) {
cryptsetup_enable_logging(cd);
r = crypt_deactivate(cd, argv[2]);
r = crypt_deactivate(cd, volume);
if (r < 0)
return log_error_errno(r, "Failed to deactivate: %m");
} 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;
}