From: Lennart Poettering Date: Sun, 16 Jul 2023 09:09:30 +0000 (+0200) Subject: pcrextend: split out word to measure code into shared helper file X-Git-Tag: v255-rc1~165 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4cdef9f08cda44ae396f2704eb4210117712a50e;p=thirdparty%2Fsystemd.git pcrextend: split out word to measure code into shared helper file Let's split out the logic that actually generates the word to measure to PCRs into a new helper file pcrextend-util.[ch]. This we can later reuse to calculate PCR measurement predictions ahead of time. --- diff --git a/src/pcrextend/pcrextend.c b/src/pcrextend/pcrextend.c index c44e78c4cab..17a81816db4 100644 --- a/src/pcrextend/pcrextend.c +++ b/src/pcrextend/pcrextend.c @@ -2,23 +2,18 @@ #include -#include #include -#include "blkid-util.h" -#include "blockdev-util.h" #include "build.h" -#include "chase.h" #include "efi-loader.h" -#include "efivars.h" #include "escape.h" -#include "fd-util.h" #include "main-func.h" -#include "mountpoint-util.h" #include "openssl-util.h" #include "parse-argument.h" #include "parse-util.h" +#include "pcrextend-util.h" #include "pretty-print.h" +#include "strv.h" #include "tpm2-pcr.h" #include "tpm2-util.h" #include "varlink.h" @@ -200,73 +195,6 @@ static int determine_banks(Tpm2Context *c, unsigned target_pcr_nr) { return 0; } -static int get_file_system_word( - sd_device *d, - const char *prefix, - char **ret) { - - int r; - - assert(d); - assert(prefix); - assert(ret); - - _cleanup_close_ int block_fd = sd_device_open(d, O_RDONLY|O_CLOEXEC|O_NONBLOCK); - if (block_fd < 0) - return block_fd; - - _cleanup_(blkid_free_probep) blkid_probe b = blkid_new_probe(); - if (!b) - return -ENOMEM; - - errno = 0; - r = blkid_probe_set_device(b, block_fd, 0, 0); - if (r != 0) - return errno_or_else(ENOMEM); - - (void) blkid_probe_enable_superblocks(b, 1); - (void) blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_UUID|BLKID_SUBLKS_LABEL); - (void) blkid_probe_enable_partitions(b, 1); - (void) blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); - - errno = 0; - r = blkid_do_safeprobe(b); - if (r == _BLKID_SAFEPROBE_ERROR) - return errno_or_else(EIO); - if (IN_SET(r, _BLKID_SAFEPROBE_AMBIGUOUS, _BLKID_SAFEPROBE_NOT_FOUND)) - return -ENOPKG; - - assert(r == _BLKID_SAFEPROBE_FOUND); - - _cleanup_strv_free_ char **l = strv_new(prefix); - if (!l) - return log_oom(); - - FOREACH_STRING(field, "TYPE", "UUID", "LABEL", "PART_ENTRY_UUID", "PART_ENTRY_TYPE", "PART_ENTRY_NAME") { - const char *v = NULL; - - (void) blkid_probe_lookup_value(b, field, &v, NULL); - - _cleanup_free_ char *escaped = xescape(strempty(v), ":"); /* Avoid ambiguity around ":" */ - if (!escaped) - return log_oom(); - - r = strv_consume(&l, TAKE_PTR(escaped)); - if (r < 0) - return log_oom(); - - } - - assert(strv_length(l) == 7); /* We always want 7 components, to avoid ambiguous strings */ - - _cleanup_free_ char *word = strv_join(l, ":"); - if (!word) - return log_oom(); - - *ret = TAKE_PTR(word); - return 0; -} - static int extend_now(unsigned pcr, const void *data, size_t size, Tpm2UserspaceEventType event) { _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL; int r; @@ -413,59 +341,23 @@ static int run(int argc, char *argv[]) { } if (arg_file_system) { - _cleanup_free_ char *normalized = NULL, *normalized_escaped = NULL; - _cleanup_(sd_device_unrefp) sd_device *d = NULL; - _cleanup_close_ int dfd = -EBADF; - if (optind != argc) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected no argument."); - dfd = chase_and_open(arg_file_system, NULL, 0, O_DIRECTORY|O_CLOEXEC, &normalized); - if (dfd < 0) - return log_error_errno(dfd, "Failed to open path '%s': %m", arg_file_system); - - r = fd_is_mount_point(dfd, NULL, 0); + r = pcrextend_file_system_word(arg_file_system, &word, NULL); if (r < 0) - return log_error_errno(r, "Failed to determine if path '%s' is mount point: %m", normalized); - if (r == 0) - return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "Specified path '%s' is not a mount point, refusing: %m", normalized); - - normalized_escaped = xescape(normalized, ":"); /* Avoid ambiguity around ":" */ - if (!normalized_escaped) - return log_oom(); - - _cleanup_free_ char* prefix = strjoin("file-system:", normalized_escaped); - if (!prefix) - return log_oom(); - - r = block_device_new_from_fd(dfd, BLOCK_DEVICE_LOOKUP_BACKING, &d); - if (r < 0) { - log_notice_errno(r, "Unable to determine backing block device of '%s', measuring generic fallback file system identity string: %m", arg_file_system); - - word = strjoin(prefix, "::::::"); - if (!word) - return log_oom(); - } else { - r = get_file_system_word(d, prefix, &word); - if (r < 0) - return log_error_errno(r, "Failed to get file system identifier string for '%s': %m", arg_file_system); - } + return r; event = TPM2_EVENT_FILESYSTEM; } else if (arg_machine_id) { - sd_id128_t mid; if (optind != argc) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected no argument."); - r = sd_id128_get_machine(&mid); + r = pcrextend_machine_id_word(&word); if (r < 0) - return log_error_errno(r, "Failed to acquire machine ID: %m"); - - word = strjoin("machine-id:", SD_ID128_TO_STRING(mid)); - if (!word) - return log_oom(); + return r; event = TPM2_EVENT_MACHINE_ID; diff --git a/src/shared/meson.build b/src/shared/meson.build index 662cb53dda2..5b20155b240 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -133,6 +133,7 @@ shared_sources = files( 'password-quality-util-passwdqc.c', 'password-quality-util-pwquality.c', 'pcre2-util.c', + 'pcrextend-util.c', 'pe-binary.c', 'pkcs11-util.c', 'pretty-print.c', diff --git a/src/shared/pcrextend-util.c b/src/shared/pcrextend-util.c new file mode 100644 index 00000000000..fa066a4327f --- /dev/null +++ b/src/shared/pcrextend-util.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "sd-device.h" + +#include "blkid-util.h" +#include "blockdev-util.h" +#include "chase.h" +#include "errno-util.h" +#include "escape.h" +#include "fd-util.h" +#include "mountpoint-util.h" +#include "pcrextend-util.h" +#include "strv.h" + +static int device_get_file_system_word( + sd_device *d, + const char *prefix, + char **ret) { + +#if HAVE_BLKID + int r; +#endif + + assert(d); + assert(prefix); + assert(ret); + +#if HAVE_BLKID + _cleanup_close_ int block_fd = sd_device_open(d, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (block_fd < 0) + return block_fd; + + _cleanup_(blkid_free_probep) blkid_probe b = blkid_new_probe(); + if (!b) + return -ENOMEM; + + errno = 0; + r = blkid_probe_set_device(b, block_fd, 0, 0); + if (r != 0) + return errno_or_else(ENOMEM); + + (void) blkid_probe_enable_superblocks(b, 1); + (void) blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_UUID|BLKID_SUBLKS_LABEL); + (void) blkid_probe_enable_partitions(b, 1); + (void) blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); + + errno = 0; + r = blkid_do_safeprobe(b); + if (r == _BLKID_SAFEPROBE_ERROR) + return errno_or_else(EIO); + if (IN_SET(r, _BLKID_SAFEPROBE_AMBIGUOUS, _BLKID_SAFEPROBE_NOT_FOUND)) + return -ENOPKG; + + assert(r == _BLKID_SAFEPROBE_FOUND); + + _cleanup_strv_free_ char **l = strv_new(prefix); + if (!l) + return -ENOMEM; + + FOREACH_STRING(field, "TYPE", "UUID", "LABEL", "PART_ENTRY_UUID", "PART_ENTRY_TYPE", "PART_ENTRY_NAME") { + const char *v = NULL; + + (void) blkid_probe_lookup_value(b, field, &v, NULL); + + _cleanup_free_ char *escaped = xescape(strempty(v), ":"); /* Avoid ambiguity around ":" */ + if (!escaped) + return -ENOMEM; + + r = strv_consume(&l, TAKE_PTR(escaped)); + if (r < 0) + return r; + } + + assert(strv_length(l) == 7); /* We always want 7 components, to avoid ambiguous strings */ + + _cleanup_free_ char *word = strv_join(l, ":"); + if (!word) + return -ENOMEM; + + *ret = TAKE_PTR(word); + return 0; +#else + return -EOPNOTSUPP; +#endif +} + +int pcrextend_file_system_word(const char *path, char **ret_word, char **ret_normalized_path) { + _cleanup_free_ char *normalized_path = NULL, *normalized_escaped = NULL, *prefix = NULL, *word = NULL; + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + _cleanup_close_ int dfd = -EBADF; + int r; + + assert(path); + assert(ret_word); + + dfd = chase_and_open(path, NULL, 0, O_DIRECTORY|O_CLOEXEC, &normalized_path); + if (dfd < 0) + return log_error_errno(dfd, "Failed to open path '%s': %m", path); + + r = fd_is_mount_point(dfd, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to determine if path '%s' is mount point: %m", normalized_path); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "Specified path '%s' is not a mount point, refusing: %m", normalized_path); + + normalized_escaped = xescape(normalized_path, ":"); /* Avoid ambiguity around ":" */ + if (!normalized_escaped) + return log_oom(); + + prefix = strjoin("file-system:", normalized_escaped); + if (!prefix) + return log_oom(); + + r = block_device_new_from_fd(dfd, BLOCK_DEVICE_LOOKUP_BACKING, &d); + if (r < 0) { + log_notice_errno(r, "Unable to determine backing block device of '%s', using generic fallback file system identity string: %m", path); + + word = strjoin(prefix, "::::::"); + if (!word) + return log_oom(); + } else { + r = device_get_file_system_word(d, prefix, &word); + if (r < 0) + return log_error_errno(r, "Failed to get file system identifier string for '%s': %m", path); + } + + *ret_word = TAKE_PTR(word); + + if (ret_normalized_path) + *ret_normalized_path = TAKE_PTR(normalized_path); + + return 0; +} + +int pcrextend_machine_id_word(char **ret) { + _cleanup_free_ char *word = NULL; + sd_id128_t mid; + int r; + + assert(ret); + + r = sd_id128_get_machine(&mid); + if (r < 0) + return log_error_errno(r, "Failed to acquire machine ID: %m"); + + word = strjoin("machine-id:", SD_ID128_TO_STRING(mid)); + if (!word) + return log_oom(); + + *ret = TAKE_PTR(word); + return 0; +} diff --git a/src/shared/pcrextend-util.h b/src/shared/pcrextend-util.h new file mode 100644 index 00000000000..7dd612b8fb8 --- /dev/null +++ b/src/shared/pcrextend-util.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +int pcrextend_file_system_word(const char *path, char **ret, char **ret_normalized_path); +int pcrextend_machine_id_word(char **ret);