/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 | } |