Coverage Report

Created: 2025-06-13 06:27

/src/systemd/src/shared/pcrextend-util.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3
#include "sd-device.h"
4
#include "sd-id128.h"
5
6
#include "alloc-util.h"
7
#include "blkid-util.h"
8
#include "blockdev-util.h"
9
#include "chase.h"
10
#include "errno-util.h"
11
#include "escape.h"
12
#include "fd-util.h"
13
#include "log.h"
14
#include "mountpoint-util.h"
15
#include "pcrextend-util.h"
16
#include "string-util.h"
17
#include "strv.h"
18
19
static int device_get_file_system_word(
20
                sd_device *d,
21
                const char *prefix,
22
0
                char **ret) {
23
24
#if HAVE_BLKID
25
        int r;
26
#endif
27
28
0
        assert(d);
29
0
        assert(prefix);
30
0
        assert(ret);
31
32
#if HAVE_BLKID
33
        _cleanup_close_ int block_fd = sd_device_open(d, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
34
        if (block_fd < 0)
35
                return block_fd;
36
37
        _cleanup_(blkid_free_probep) blkid_probe b = blkid_new_probe();
38
        if (!b)
39
                return -ENOMEM;
40
41
        errno = 0;
42
        r = blkid_probe_set_device(b, block_fd, 0, 0);
43
        if (r != 0)
44
                return errno_or_else(ENOMEM);
45
46
        (void) blkid_probe_enable_superblocks(b, 1);
47
        (void) blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_UUID|BLKID_SUBLKS_LABEL);
48
        (void) blkid_probe_enable_partitions(b, 1);
49
        (void) blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
50
51
        errno = 0;
52
        r = blkid_do_safeprobe(b);
53
        if (r == _BLKID_SAFEPROBE_ERROR)
54
                return errno_or_else(EIO);
55
        if (IN_SET(r, _BLKID_SAFEPROBE_AMBIGUOUS, _BLKID_SAFEPROBE_NOT_FOUND))
56
                return -ENOPKG;
57
58
        assert(r == _BLKID_SAFEPROBE_FOUND);
59
60
        _cleanup_strv_free_ char **l = strv_new(prefix);
61
        if (!l)
62
                return -ENOMEM;
63
64
        FOREACH_STRING(field, "TYPE", "UUID", "LABEL", "PART_ENTRY_UUID", "PART_ENTRY_TYPE", "PART_ENTRY_NAME") {
65
                const char *v = NULL;
66
67
                (void) blkid_probe_lookup_value(b, field, &v, NULL);
68
69
                _cleanup_free_ char *escaped = xescape(strempty(v), ":"); /* Avoid ambiguity around ":" */
70
                if (!escaped)
71
                        return -ENOMEM;
72
73
                r = strv_consume(&l, TAKE_PTR(escaped));
74
                if (r < 0)
75
                        return r;
76
        }
77
78
        assert(strv_length(l) == 7); /* We always want 7 components, to avoid ambiguous strings */
79
80
        _cleanup_free_ char *word = strv_join(l, ":");
81
        if (!word)
82
                return -ENOMEM;
83
84
        *ret = TAKE_PTR(word);
85
        return 0;
86
#else
87
0
        return -EOPNOTSUPP;
88
0
#endif
89
0
}
90
91
0
int pcrextend_file_system_word(const char *path, char **ret_word, char **ret_normalized_path) {
92
0
        _cleanup_free_ char *normalized_path = NULL, *normalized_escaped = NULL, *prefix = NULL, *word = NULL;
93
0
        _cleanup_(sd_device_unrefp) sd_device *d = NULL;
94
0
        _cleanup_close_ int dfd = -EBADF;
95
0
        int r;
96
97
0
        assert(path);
98
0
        assert(ret_word);
99
100
0
        dfd = chase_and_open(path, NULL, 0, O_DIRECTORY|O_CLOEXEC, &normalized_path);
101
0
        if (dfd < 0)
102
0
                return log_error_errno(dfd, "Failed to open path '%s': %m", path);
103
104
0
        r = is_mount_point_at(dfd, NULL, 0);
105
0
        if (r < 0)
106
0
                return log_error_errno(r, "Failed to determine if path '%s' is mount point: %m", normalized_path);
107
0
        if (r == 0)
108
0
                return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "Specified path '%s' is not a mount point, refusing.", normalized_path);
109
110
0
        normalized_escaped = xescape(normalized_path, ":"); /* Avoid ambiguity around ":" */
111
0
        if (!normalized_escaped)
112
0
                return log_oom();
113
114
0
        prefix = strjoin("file-system:", normalized_escaped);
115
0
        if (!prefix)
116
0
                return log_oom();
117
118
0
        r = block_device_new_from_fd(dfd, BLOCK_DEVICE_LOOKUP_BACKING, &d);
119
0
        if (r < 0) {
120
0
                log_notice_errno(r, "Unable to determine backing block device of '%s', using generic fallback file system identity string: %m", path);
121
122
0
                word = strjoin(prefix, "::::::");
123
0
                if (!word)
124
0
                        return log_oom();
125
0
        } else {
126
0
                r = device_get_file_system_word(d, prefix, &word);
127
0
                if (r < 0)
128
0
                        return log_error_errno(r, "Failed to get file system identifier string for '%s': %m", path);
129
0
        }
130
131
0
        *ret_word = TAKE_PTR(word);
132
133
0
        if (ret_normalized_path)
134
0
                *ret_normalized_path = TAKE_PTR(normalized_path);
135
136
0
        return 0;
137
0
}
138
139
0
int pcrextend_machine_id_word(char **ret) {
140
0
        _cleanup_free_ char *word = NULL;
141
0
        sd_id128_t mid;
142
0
        int r;
143
144
0
        assert(ret);
145
146
0
        r = sd_id128_get_machine(&mid);
147
0
        if (r < 0)
148
0
                return log_error_errno(r, "Failed to acquire machine ID: %m");
149
150
0
        word = strjoin("machine-id:", SD_ID128_TO_STRING(mid));
151
0
        if (!word)
152
0
                return log_oom();
153
154
0
        *ret = TAKE_PTR(word);
155
0
        return 0;
156
0
}