/
niceSOFT
/
systemd
Обзор
Документация
Войти
/
niceSOFT
/
systemd
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
v260
src/integritysetup/integritysetup.c
206 строк
7 KB
Yu Watanabe
tree-wide: normalize comment style
15 дек 2025, 02:50
15 дек 2025, 02:50
9337814
Код
Авторство
О чём код?
/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include <stdio.h> #include <sys/stat.h> #include "alloc-util.h" #include "argv-util.h" #include "cryptsetup-util.h" #include "fileio.h" #include "integrity-util.h" #include "log.h" #include "main-func.h" #include "path-util.h" #include "pretty-print.h" #include "string-util.h" #include "time-util.h" #include "verbs.h" static uint32_t arg_activate_flags; static int arg_percent; static usec_t arg_commit_time; static char *arg_existing_data_device; static char *arg_integrity_algorithm; STATIC_DESTRUCTOR_REGISTER(arg_existing_data_device, freep); STATIC_DESTRUCTOR_REGISTER(arg_integrity_algorithm, freep); static int help(void) { _cleanup_free_ char *link = NULL; int r; r = terminal_urlify_man("systemd-integritysetup@.service", "8", &link); if (r < 0) return log_oom(); printf("%s attach VOLUME DEVICE [HMAC_KEY_FILE|-] [OPTIONS]\n" "%s detach VOLUME\n\n" "Attach or detach an integrity protected block device.\n" "\nSee the %s for details.\n", program_invocation_short_name, program_invocation_short_name, link); return 0; } static int load_key_file( const char *key_file, void **ret_key_file_contents, size_t *ret_key_file_size) { int r; _cleanup_(erase_and_freep) char *tmp_key_file_contents = NULL; size_t tmp_key_file_size; if (!path_is_absolute(key_file)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "key file not absolute path: %s", key_file); r = read_full_file_full( AT_FDCWD, key_file, UINT64_MAX, DM_MAX_KEY_SIZE, READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET|READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &tmp_key_file_contents, &tmp_key_file_size); if (r < 0) return log_error_errno(r, "Failed to process key file: %m"); if (ret_key_file_contents && ret_key_file_size) { *ret_key_file_contents = TAKE_PTR(tmp_key_file_contents); *ret_key_file_size = tmp_key_file_size; } return 0; } static const char *integrity_algorithm_select(const void *key_file_buf) { /* To keep a bit of sanity for end users, the subset of integrity * algorithms we support will match what is used in integritysetup */ if (arg_integrity_algorithm) { if (streq(arg_integrity_algorithm, "hmac-sha256")) return DM_HMAC_256; if (streq(arg_integrity_algorithm, "hmac-sha512")) return DM_HMAC_512; if (streq(arg_integrity_algorithm, "phmac-sha256")) return DM_PHMAC_256; if (streq(arg_integrity_algorithm, "phmac-sha512")) return DM_PHMAC_512; return arg_integrity_algorithm; } else if (key_file_buf) return DM_HMAC_256; return "crc32c"; } static int verb_attach(int argc, char *argv[], void *userdata) { _cleanup_(crypt_freep) struct crypt_device *cd = NULL; crypt_status_info status; _cleanup_(erase_and_freep) void *key_buf = NULL; size_t key_buf_size = 0; int r; /* attach name device optional_key_file optional_options */ assert(argc >= 3 && argc <= 5); const char *volume = argv[1], *device = argv[2], *key_file = mangle_none(argc > 3 ? argv[3] : NULL), *options = mangle_none(argc > 4 ? argv[4] : 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); if (r < 0) return r; } if (options) { r = parse_integrity_options(options, &arg_activate_flags, &arg_percent, &arg_commit_time, &arg_existing_data_device, &arg_integrity_algorithm); if (r < 0) return r; } r = crypt_init(&cd, device); if (r < 0) return log_error_errno(r, "Failed to open integrity device %s: %m", device); cryptsetup_enable_logging(cd); status = crypt_status(cd, volume); if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) { log_info("Volume %s already active.", volume); return 0; } r = crypt_load(cd, CRYPT_INTEGRITY, &(struct crypt_params_integrity) { .journal_watermark = arg_percent, .journal_commit_time = DIV_ROUND_UP(arg_commit_time, USEC_PER_SEC), .integrity = integrity_algorithm_select(key_buf), }); if (r < 0) return log_error_errno(r, "Failed to load integrity superblock: %m"); if (!isempty(arg_existing_data_device)) { r = crypt_set_data_device(cd, arg_existing_data_device); if (r < 0) return log_error_errno(r, "Failed to add separate data device: %m"); } r = crypt_activate_by_volume_key(cd, volume, key_buf, key_buf_size, arg_activate_flags); if (r < 0) return log_error_errno(r, "Failed to set up integrity device: %m"); return 0; } static int verb_detach(int argc, char *argv[], void *userdata) { _cleanup_(crypt_freep) struct crypt_device *cd = NULL; int r; assert(argc == 2); const char *volume = argv[1]; 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.", volume); return 0; } if (r < 0) return log_error_errno(r, "crypt_init_by_name() failed: %m"); cryptsetup_enable_logging(cd); r = crypt_deactivate(cd, volume); if (r < 0) return log_error_errno(r, "Failed to deactivate: %m"); return 0; } static int run(int argc, char *argv[]) { if (argv_looks_like_help(argc, argv)) return help(); log_setup(); cryptsetup_enable_logging(NULL); umask(0022); static const Verb verbs[] = { { "attach", 3, 5, 0, verb_attach }, { "detach", 2, 2, 0, verb_detach }, {} }; return dispatch_verb(argc, argv, verbs, NULL); } DEFINE_MAIN_FUNCTION(run);