]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pcrextend: split out word to measure code into shared helper file
authorLennart Poettering <lennart@poettering.net>
Sun, 16 Jul 2023 09:09:30 +0000 (11:09 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Mon, 23 Oct 2023 10:24:18 +0000 (11:24 +0100)
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.

src/pcrextend/pcrextend.c
src/shared/meson.build
src/shared/pcrextend-util.c [new file with mode: 0644]
src/shared/pcrextend-util.h [new file with mode: 0644]

index c44e78c4cab56decb7c3a194799a8a2021db41f3..17a81816db4de954802ac47ea5d0afff3a07d9dc 100644 (file)
@@ -2,23 +2,18 @@
 
 #include <getopt.h>
 
-#include <sd-device.h>
 #include <sd-messages.h>
 
-#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;
 
index 662cb53dda2ad50c5d5530da5bcdac005ac9817d..5b20155b24009d1370671a5341fc5811cbbbd5aa 100644 (file)
@@ -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 (file)
index 0000000..fa066a4
--- /dev/null
@@ -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 (file)
index 0000000..7dd612b
--- /dev/null
@@ -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);