Bug Summary

File:build-scan/../src/shared/bootspec.c
Warning:line 268, column 9
Declared variable-length array (VLA) has zero size

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name bootspec.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/shared/libsystemd-shared-239.a.p -I src/shared -I ../src/shared -I src/basic -I ../src/basic -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/shared/bootspec.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <stdio.h>
4#include <linux1/magic.h>
5
6#include "sd-id128.h"
7
8#include "alloc-util.h"
9#include "blkid-util.h"
10#include "bootspec.h"
11#include "conf-files.h"
12#include "def.h"
13#include "device-nodes.h"
14#include "efivars.h"
15#include "fd-util.h"
16#include "fileio.h"
17#include "parse-util.h"
18#include "stat-util.h"
19#include "string-util.h"
20#include "strv.h"
21#include "virt.h"
22
23void boot_entry_free(BootEntry *entry) {
24 assert(entry)do { if ((__builtin_expect(!!(!(entry)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("entry"), "../src/shared/bootspec.c", 24
, __PRETTY_FUNCTION__); } while (0)
;
25
26 free(entry->filename);
27 free(entry->title);
28 free(entry->show_title);
29 free(entry->version);
30 free(entry->machine_id);
31 free(entry->architecture);
32 strv_free(entry->options);
33 free(entry->kernel);
34 free(entry->efi);
35 strv_free(entry->initrd);
36 free(entry->device_tree);
37}
38
39int boot_entry_load(const char *path, BootEntry *entry) {
40 _cleanup_(boot_entry_free)__attribute__((cleanup(boot_entry_free))) BootEntry tmp = {};
41 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
42 unsigned line = 1;
43 char *b, *c;
44 int r;
45
46 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/shared/bootspec.c", 46,
__PRETTY_FUNCTION__); } while (0)
;
47 assert(entry)do { if ((__builtin_expect(!!(!(entry)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("entry"), "../src/shared/bootspec.c", 47
, __PRETTY_FUNCTION__); } while (0)
;
48
49 c = endswith_no_case(path, ".conf");
50 if (!c) {
51 log_error("Invalid loader entry filename: %s", path)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 51, __func__, "Invalid loader entry filename: %s"
, path) : -abs(_e); })
;
52 return -EINVAL22;
53 }
54
55 b = basename(path);
56 tmp.filename = strndup(b, c - b);
57 if (!tmp.filename)
58 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/shared/bootspec.c"
, 58, __func__)
;
59
60 f = fopen(path, "re");
61 if (!f)
62 return log_error_errno(errno, "Failed to open \"%s\": %m", path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 62, __func__
, "Failed to open \"%s\": %m", path) : -abs(_e); })
;
63
64 for (;;) {
65 _cleanup_free___attribute__((cleanup(freep))) char *buf = NULL((void*)0), *field = NULL((void*)0);
66 const char *p;
67
68 r = read_line(f, LONG_LINE_MAX(1U*1024U*1024U), &buf);
69 if (r == 0)
70 break;
71 if (r == -ENOBUFS105)
72 return log_error_errno(r, "%s:%u: Line too long", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 72, __func__, "%s:%u: Line too long"
, path, line) : -abs(_e); })
;
73 if (r < 0)
74 return log_error_errno(r, "%s:%u: Error while reading: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 74, __func__, "%s:%u: Error while reading: %m"
, path, line) : -abs(_e); })
;
75
76 line++;
77
78 if (IN_SET(*strstrip(buf), '#', '\0')({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){'#', '\0'})/sizeof(int)]; switch(*strstrip
(buf)) { case '#': case '\0': _found = 1; break; default: break
; } _found; })
)
79 continue;
80
81 p = buf;
82 r = extract_first_word(&p, &field, " \t", 0);
83 if (r < 0) {
84 log_error_errno(r, "Failed to parse config file %s line %u: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 84, __func__, "Failed to parse config file %s line %u: %m"
, path, line) : -abs(_e); })
;
85 continue;
86 }
87 if (r == 0) {
88 log_warning("%s:%u: Bad syntax", path, line)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 88, __func__, "%s:%u: Bad syntax"
, path, line) : -abs(_e); })
;
89 continue;
90 }
91
92 if (streq(field, "title")(strcmp((field),("title")) == 0))
93 r = free_and_strdup(&tmp.title, p);
94 else if (streq(field, "version")(strcmp((field),("version")) == 0))
95 r = free_and_strdup(&tmp.version, p);
96 else if (streq(field, "machine-id")(strcmp((field),("machine-id")) == 0))
97 r = free_and_strdup(&tmp.machine_id, p);
98 else if (streq(field, "architecture")(strcmp((field),("architecture")) == 0))
99 r = free_and_strdup(&tmp.architecture, p);
100 else if (streq(field, "options")(strcmp((field),("options")) == 0))
101 r = strv_extend(&tmp.options, p);
102 else if (streq(field, "linux")(strcmp((field),("linux")) == 0))
103 r = free_and_strdup(&tmp.kernel, p);
104 else if (streq(field, "efi")(strcmp((field),("efi")) == 0))
105 r = free_and_strdup(&tmp.efi, p);
106 else if (streq(field, "initrd")(strcmp((field),("initrd")) == 0))
107 r = strv_extend(&tmp.initrd, p);
108 else if (streq(field, "devicetree")(strcmp((field),("devicetree")) == 0))
109 r = free_and_strdup(&tmp.device_tree, p);
110 else {
111 log_notice("%s:%u: Unknown line \"%s\"", path, line, field)({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 111, __func__, "%s:%u: Unknown line \"%s\""
, path, line, field) : -abs(_e); })
;
112 continue;
113 }
114 if (r < 0)
115 return log_error_errno(r, "%s:%u: Error while reading: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 115, __func__, "%s:%u: Error while reading: %m"
, path, line) : -abs(_e); })
;
116 }
117
118 *entry = tmp;
119 tmp = (BootEntry) {};
120 return 0;
121}
122
123void boot_config_free(BootConfig *config) {
124 size_t i;
125
126 assert(config)do { if ((__builtin_expect(!!(!(config)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("config"), "../src/shared/bootspec.c", 126
, __PRETTY_FUNCTION__); } while (0)
;
127
128 free(config->default_pattern);
129 free(config->timeout);
130 free(config->editor);
131 free(config->auto_entries);
132 free(config->auto_firmware);
133
134 free(config->entry_oneshot);
135 free(config->entry_default);
136
137 for (i = 0; i < config->n_entries; i++)
138 boot_entry_free(config->entries + i);
139 free(config->entries);
140}
141
142int boot_loader_read_conf(const char *path, BootConfig *config) {
143 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
144 unsigned line = 1;
145 int r;
146
147 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/shared/bootspec.c", 147
, __PRETTY_FUNCTION__); } while (0)
;
12
Taking false branch
13
Loop condition is false. Exiting loop
148 assert(config)do { if ((__builtin_expect(!!(!(config)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("config"), "../src/shared/bootspec.c", 148
, __PRETTY_FUNCTION__); } while (0)
;
14
Taking false branch
15
Loop condition is false. Exiting loop
149
150 f = fopen(path, "re");
151 if (!f)
16
Assuming 'f' is non-null
17
Taking false branch
152 return log_error_errno(errno, "Failed to open \"%s\": %m", path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 152, __func__
, "Failed to open \"%s\": %m", path) : -abs(_e); })
;
153
154 for (;;) {
18
Loop condition is true. Entering loop body
155 _cleanup_free___attribute__((cleanup(freep))) char *buf = NULL((void*)0), *field = NULL((void*)0);
156 const char *p;
157
158 r = read_line(f, LONG_LINE_MAX(1U*1024U*1024U), &buf);
159 if (r == 0)
19
Assuming 'r' is equal to 0
20
Taking true branch
160 break;
21
Execution continues on line 202
161 if (r == -ENOBUFS105)
162 return log_error_errno(r, "%s:%u: Line too long", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 162, __func__, "%s:%u: Line too long"
, path, line) : -abs(_e); })
;
163 if (r < 0)
164 return log_error_errno(r, "%s:%u: Error while reading: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 164, __func__, "%s:%u: Error while reading: %m"
, path, line) : -abs(_e); })
;
165
166 line++;
167
168 if (IN_SET(*strstrip(buf), '#', '\0')({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){'#', '\0'})/sizeof(int)]; switch(*strstrip
(buf)) { case '#': case '\0': _found = 1; break; default: break
; } _found; })
)
169 continue;
170
171 p = buf;
172 r = extract_first_word(&p, &field, " \t", 0);
173 if (r < 0) {
174 log_error_errno(r, "Failed to parse config file %s line %u: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 174, __func__, "Failed to parse config file %s line %u: %m"
, path, line) : -abs(_e); })
;
175 continue;
176 }
177 if (r == 0) {
178 log_warning("%s:%u: Bad syntax", path, line)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 178, __func__, "%s:%u: Bad syntax"
, path, line) : -abs(_e); })
;
179 continue;
180 }
181
182 if (streq(field, "default")(strcmp((field),("default")) == 0))
183 r = free_and_strdup(&config->default_pattern, p);
184 else if (streq(field, "timeout")(strcmp((field),("timeout")) == 0))
185 r = free_and_strdup(&config->timeout, p);
186 else if (streq(field, "editor")(strcmp((field),("editor")) == 0))
187 r = free_and_strdup(&config->editor, p);
188 else if (streq(field, "auto-entries")(strcmp((field),("auto-entries")) == 0))
189 r = free_and_strdup(&config->auto_entries, p);
190 else if (streq(field, "auto-firmware")(strcmp((field),("auto-firmware")) == 0))
191 r = free_and_strdup(&config->auto_firmware, p);
192 else if (streq(field, "console-mode")(strcmp((field),("console-mode")) == 0))
193 r = free_and_strdup(&config->console_mode, p);
194 else {
195 log_notice("%s:%u: Unknown line \"%s\"", path, line, field)({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 195, __func__, "%s:%u: Unknown line \"%s\""
, path, line, field) : -abs(_e); })
;
196 continue;
197 }
198 if (r < 0)
199 return log_error_errno(r, "%s:%u: Error while reading: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 199, __func__, "%s:%u: Error while reading: %m"
, path, line) : -abs(_e); })
;
200 }
201
202 return 0;
22
Returning without writing to 'config->n_entries'
203}
204
205static int boot_entry_compare(const void *a, const void *b) {
206 const BootEntry *aa = a, *bb = b;
207
208 return str_verscmp(aa->filename, bb->filename);
209}
210
211int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *ret_n_entries) {
212 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **files = NULL((void*)0);
213 char **f;
214 int r;
215 BootEntry *array = NULL((void*)0);
216 size_t n_allocated = 0, n = 0;
30
'n' initialized to 0
217
218 assert(dir)do { if ((__builtin_expect(!!(!(dir)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("dir"), "../src/shared/bootspec.c", 218,
__PRETTY_FUNCTION__); } while (0)
;
31
Taking false branch
32
Loop condition is false. Exiting loop
219 assert(ret_entries)do { if ((__builtin_expect(!!(!(ret_entries)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_entries"), "../src/shared/bootspec.c"
, 219, __PRETTY_FUNCTION__); } while (0)
;
33
Taking false branch
34
Loop condition is false. Exiting loop
220 assert(ret_n_entries)do { if ((__builtin_expect(!!(!(ret_n_entries)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_n_entries"), "../src/shared/bootspec.c"
, 220, __PRETTY_FUNCTION__); } while (0)
;
35
Taking false branch
36
Loop condition is false. Exiting loop
221
222 r = conf_files_list(&files, ".conf", NULL((void*)0), 0, dir, NULL((void*)0));
223 if (r < 0)
37
Assuming 'r' is >= 0
38
Taking false branch
224 return log_error_errno(r, "Failed to list files in \"%s\": %m", dir)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 224, __func__, "Failed to list files in \"%s\": %m"
, dir) : -abs(_e); })
;
225
226 STRV_FOREACH(f, files)for ((f) = (files); (f) && *(f); (f)++) {
39
Assuming 'f' is null
227 if (!GREEDY_REALLOC0(array, n_allocated, n + 1)greedy_realloc0((void**) &(array), &(n_allocated), (n
+ 1), sizeof((array)[0]))
)
228 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/shared/bootspec.c"
, 228, __func__)
;
229
230 r = boot_entry_load(*f, array + n);
231 if (r < 0)
232 continue;
233
234 n++;
235 }
236
237 qsort_safe(array, n, sizeof(BootEntry), boot_entry_compare);
238
239 *ret_entries = array;
240 *ret_n_entries = n;
40
The value 0 is assigned to field 'n_entries'
241
242 return 0;
243}
244
245static bool_Bool find_nonunique(BootEntry *entries, size_t n_entries, bool_Bool *arr) {
246 size_t i, j;
247 bool_Bool non_unique = false0;
248
249 assert(entries || n_entries == 0)do { if ((__builtin_expect(!!(!(entries || n_entries == 0)),0
))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("entries || n_entries == 0"
), "../src/shared/bootspec.c", 249, __PRETTY_FUNCTION__); } while
(0)
;
250 assert(arr || n_entries == 0)do { if ((__builtin_expect(!!(!(arr || n_entries == 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("arr || n_entries == 0"), "../src/shared/bootspec.c"
, 250, __PRETTY_FUNCTION__); } while (0)
;
251
252 for (i = 0; i < n_entries; i++)
253 arr[i] = false0;
254
255 for (i = 0; i < n_entries; i++)
256 for (j = 0; j < n_entries; j++)
257 if (i != j && streq(boot_entry_title(entries + i),(strcmp((boot_entry_title(entries + i)),(boot_entry_title(entries
+ j))) == 0)
258 boot_entry_title(entries + j))(strcmp((boot_entry_title(entries + i)),(boot_entry_title(entries
+ j))) == 0)
)
259 non_unique = arr[i] = arr[j] = true1;
260
261 return non_unique;
262}
263
264static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
265 char *s;
266 size_t i;
267 int r;
268 bool_Bool arr[n_entries];
45
Declared variable-length array (VLA) has zero size
269
270 assert(entries || n_entries == 0)do { if ((__builtin_expect(!!(!(entries || n_entries == 0)),0
))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("entries || n_entries == 0"
), "../src/shared/bootspec.c", 270, __PRETTY_FUNCTION__); } while
(0)
;
271
272 /* Find _all_ non-unique titles */
273 if (!find_nonunique(entries, n_entries, arr))
274 return 0;
275
276 /* Add version to non-unique titles */
277 for (i = 0; i < n_entries; i++)
278 if (arr[i] && entries[i].version) {
279 r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version);
280 if (r < 0)
281 return -ENOMEM12;
282
283 free_and_replace(entries[i].show_title, s)({ free(entries[i].show_title); (entries[i].show_title) = (s)
; (s) = ((void*)0); 0; })
;
284 }
285
286 if (!find_nonunique(entries, n_entries, arr))
287 return 0;
288
289 /* Add machine-id to non-unique titles */
290 for (i = 0; i < n_entries; i++)
291 if (arr[i] && entries[i].machine_id) {
292 r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id);
293 if (r < 0)
294 return -ENOMEM12;
295
296 free_and_replace(entries[i].show_title, s)({ free(entries[i].show_title); (entries[i].show_title) = (s)
; (s) = ((void*)0); 0; })
;
297 }
298
299 if (!find_nonunique(entries, n_entries, arr))
300 return 0;
301
302 /* Add file name to non-unique titles */
303 for (i = 0; i < n_entries; i++)
304 if (arr[i]) {
305 r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].filename);
306 if (r < 0)
307 return -ENOMEM12;
308
309 free_and_replace(entries[i].show_title, s)({ free(entries[i].show_title); (entries[i].show_title) = (s)
; (s) = ((void*)0); 0; })
;
310 }
311
312 return 0;
313}
314
315static int boot_entries_select_default(const BootConfig *config) {
316 int i;
317
318 assert(config)do { if ((__builtin_expect(!!(!(config)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("config"), "../src/shared/bootspec.c", 318
, __PRETTY_FUNCTION__); } while (0)
;
319
320 if (config->entry_oneshot)
321 for (i = config->n_entries - 1; i >= 0; i--)
322 if (streq(config->entry_oneshot, config->entries[i].filename)(strcmp((config->entry_oneshot),(config->entries[i].filename
)) == 0)
) {
323 log_debug("Found default: filename \"%s\" is matched by LoaderEntryOneShot",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 324, __func__, "Found default: filename \"%s\" is matched by LoaderEntryOneShot"
, config->entries[i].filename) : -abs(_e); })
324 config->entries[i].filename)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 324, __func__, "Found default: filename \"%s\" is matched by LoaderEntryOneShot"
, config->entries[i].filename) : -abs(_e); })
;
325 return i;
326 }
327
328 if (config->entry_default)
329 for (i = config->n_entries - 1; i >= 0; i--)
330 if (streq(config->entry_default, config->entries[i].filename)(strcmp((config->entry_default),(config->entries[i].filename
)) == 0)
) {
331 log_debug("Found default: filename \"%s\" is matched by LoaderEntryDefault",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 332, __func__, "Found default: filename \"%s\" is matched by LoaderEntryDefault"
, config->entries[i].filename) : -abs(_e); })
332 config->entries[i].filename)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 332, __func__, "Found default: filename \"%s\" is matched by LoaderEntryDefault"
, config->entries[i].filename) : -abs(_e); })
;
333 return i;
334 }
335
336 if (config->default_pattern)
337 for (i = config->n_entries - 1; i >= 0; i--)
338 if (fnmatch(config->default_pattern, config->entries[i].filename, FNM_CASEFOLD(1 << 4)) == 0) {
339 log_debug("Found default: filename \"%s\" is matched by pattern \"%s\"",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 340, __func__, "Found default: filename \"%s\" is matched by pattern \"%s\""
, config->entries[i].filename, config->default_pattern)
: -abs(_e); })
340 config->entries[i].filename, config->default_pattern)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 340, __func__, "Found default: filename \"%s\" is matched by pattern \"%s\""
, config->entries[i].filename, config->default_pattern)
: -abs(_e); })
;
341 return i;
342 }
343
344 if (config->n_entries > 0)
345 log_debug("Found default: last entry \"%s\"", config->entries[config->n_entries - 1].filename)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 345, __func__, "Found default: last entry \"%s\""
, config->entries[config->n_entries - 1].filename) : -abs
(_e); })
;
346 else
347 log_debug("Found no default boot entry :(")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 347, __func__, "Found no default boot entry :("
) : -abs(_e); })
;
348
349 return config->n_entries - 1; /* -1 means "no default" */
350}
351
352int boot_entries_load_config(const char *esp_path, BootConfig *config) {
353 const char *p;
354 int r;
355
356 assert(esp_path)do { if ((__builtin_expect(!!(!(esp_path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("esp_path"), "../src/shared/bootspec.c",
356, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 'esp_path' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
357 assert(config)do { if ((__builtin_expect(!!(!(config)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("config"), "../src/shared/bootspec.c", 357
, __PRETTY_FUNCTION__); } while (0)
;
4
Assuming 'config' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
358
359 p = strjoina(esp_path, "/loader/loader.conf")({ const char *_appendees_[] = { esp_path, "/loader/loader.conf"
}; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ =
0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
7
Loop condition is true. Entering loop body
8
Loop condition is true. Entering loop body
9
Loop condition is true. Entering loop body
10
Loop condition is true. Entering loop body
360 r = boot_loader_read_conf(p, config);
11
Calling 'boot_loader_read_conf'
23
Returning from 'boot_loader_read_conf'
361 if (r
23.1
'r' is >= 0
< 0)
24
Taking false branch
362 return log_error_errno(r, "Failed to read boot config from \"%s\": %m", p)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 362, __func__, "Failed to read boot config from \"%s\": %m"
, p) : -abs(_e); })
;
363
364 p = strjoina(esp_path, "/loader/entries")({ const char *_appendees_[] = { esp_path, "/loader/entries" }
; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0
; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
25
Loop condition is true. Entering loop body
26
Loop condition is true. Entering loop body
27
Loop condition is true. Entering loop body
28
Loop condition is true. Entering loop body
365 r = boot_entries_find(p, &config->entries, &config->n_entries);
29
Calling 'boot_entries_find'
41
Returning from 'boot_entries_find'
366 if (r
41.1
'r' is >= 0
< 0)
42
Taking false branch
367 return log_error_errno(r, "Failed to read boot entries from \"%s\": %m", p)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 367, __func__, "Failed to read boot entries from \"%s\": %m"
, p) : -abs(_e); })
;
368
369 r = boot_entries_uniquify(config->entries, config->n_entries);
43
Passing the value 0 via 2nd parameter 'n_entries'
44
Calling 'boot_entries_uniquify'
370 if (r < 0)
371 return log_error_errno(r, "Failed to uniquify boot entries: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 371, __func__, "Failed to uniquify boot entries: %m"
) : -abs(_e); })
;
372
373 r = efi_get_variable_string(EFI_VENDOR_LOADER((const sd_id128_t) { .bytes = { 0x4a, 0x67, 0xb0, 0x82, 0x0a
, 0x4c, 0x41, 0xcf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c,
0x4f }})
, "LoaderEntryOneShot", &config->entry_oneshot);
374 if (r < 0 && r != -ENOENT2)
375 return log_error_errno(r, "Failed to read EFI var \"LoaderEntryOneShot\": %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 375, __func__, "Failed to read EFI var \"LoaderEntryOneShot\": %m"
) : -abs(_e); })
;
376
377 r = efi_get_variable_string(EFI_VENDOR_LOADER((const sd_id128_t) { .bytes = { 0x4a, 0x67, 0xb0, 0x82, 0x0a
, 0x4c, 0x41, 0xcf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c,
0x4f }})
, "LoaderEntryDefault", &config->entry_default);
378 if (r < 0 && r != -ENOENT2)
379 return log_error_errno(r, "Failed to read EFI var \"LoaderEntryDefault\": %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 379, __func__, "Failed to read EFI var \"LoaderEntryDefault\": %m"
) : -abs(_e); })
;
380
381 config->default_entry = boot_entries_select_default(config);
382 return 0;
383}
384
385/********************************************************************************/
386
387static int verify_esp(
388 const char *p,
389 bool_Bool searching,
390 bool_Bool unprivileged_mode,
391 uint32_t *ret_part,
392 uint64_t *ret_pstart,
393 uint64_t *ret_psize,
394 sd_id128_t *ret_uuid) {
395#if HAVE_BLKID1
396 _cleanup_(blkid_free_probep)__attribute__((cleanup(blkid_free_probep))) blkid_probe b = NULL((void*)0);
397 char t[DEV_NUM_PATH_MAX((sizeof("""/dev/block/""") - 1) + (2+(sizeof(dev_t) <= 1 ?
3 : sizeof(dev_t) <= 2 ? 5 : sizeof(dev_t) <= 4 ? 10 :
sizeof(dev_t) <= 8 ? 20 : sizeof(int[-2*(sizeof(dev_t) >
8)]))) + 1 + (2+(sizeof(dev_t) <= 1 ? 3 : sizeof(dev_t) <=
2 ? 5 : sizeof(dev_t) <= 4 ? 10 : sizeof(dev_t) <= 8 ?
20 : sizeof(int[-2*(sizeof(dev_t) > 8)]))))
];
398 const char *v;
399#endif
400 uint64_t pstart = 0, psize = 0;
401 struct stat st, st2;
402 const char *t2;
403 struct statfs sfs;
404 sd_id128_t uuid = SD_ID128_NULL((const sd_id128_t) { .qwords = { 0, 0 }});
405 uint32_t part = 0;
406 int r;
407
408 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/shared/bootspec.c", 408, __PRETTY_FUNCTION__
); } while (0)
;
409
410 /* Non-root user can only check the status, so if an error occured in the following, it does not cause any
411 * issues. Let's also, silence the error messages. */
412
413 if (statfs(p, &sfs) < 0) {
414 /* If we are searching for the mount point, don't generate a log message if we can't find the path */
415 if (errno(*__errno_location ()) == ENOENT2 && searching)
416 return -ENOENT2;
417
418 return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,({ int _level = ((unprivileged_mode && (*__errno_location
()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 419, __func__
, "Failed to check file system type of \"%s\": %m", p) : -abs
(_e); })
419 "Failed to check file system type of \"%s\": %m", p)({ int _level = ((unprivileged_mode && (*__errno_location
()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 419, __func__
, "Failed to check file system type of \"%s\": %m", p) : -abs
(_e); })
;
420 }
421
422 if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC)(sfs.f_type == (typeof(sfs.f_type)) 0x4d44)) {
423 if (searching)
424 return -EADDRNOTAVAIL99;
425
426 log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 426, __func__, "File system \"%s\" is not a FAT EFI System Partition (ESP) file system."
, p) : -abs(_e); })
;
427 return -ENODEV19;
428 }
429
430 if (stat(p, &st) < 0)
431 return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,({ int _level = ((unprivileged_mode && (*__errno_location
()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 432, __func__
, "Failed to determine block device node of \"%s\": %m", p) :
-abs(_e); })
432 "Failed to determine block device node of \"%s\": %m", p)({ int _level = ((unprivileged_mode && (*__errno_location
()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 432, __func__
, "Failed to determine block device node of \"%s\": %m", p) :
-abs(_e); })
;
433
434 if (major(st.st_dev)gnu_dev_major (st.st_dev) == 0) {
435 log_error("Block device node of %p is invalid.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 435, __func__, "Block device node of %p is invalid."
, p) : -abs(_e); })
;
436 return -ENODEV19;
437 }
438
439 t2 = strjoina(p, "/..")({ const char *_appendees_[] = { p, "/.." }; char *_d_, *_p_;
size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
440 r = stat(t2, &st2);
441 if (r < 0)
442 return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,({ int _level = ((unprivileged_mode && (*__errno_location
()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 443, __func__
, "Failed to determine block device node of parent of \"%s\": %m"
, p) : -abs(_e); })
443 "Failed to determine block device node of parent of \"%s\": %m", p)({ int _level = ((unprivileged_mode && (*__errno_location
()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 443, __func__
, "Failed to determine block device node of parent of \"%s\": %m"
, p) : -abs(_e); })
;
444
445 if (st.st_dev == st2.st_dev) {
446 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 446, __func__, "Directory \"%s\" is not the root of the EFI System Partition (ESP) file system."
, p) : -abs(_e); })
;
447 return -ENODEV19;
448 }
449
450 /* In a container we don't have access to block devices, skip this part of the verification, we trust the
451 * container manager set everything up correctly on its own. Also skip the following verification for non-root user. */
452 if (detect_container() > 0 || unprivileged_mode)
453 goto finish;
454
455#if HAVE_BLKID1
456 xsprintf_dev_num_path(t, "block", st.st_dev)do { if ((__builtin_expect(!!(!(((size_t) snprintf(t, __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(t), typeof(&*(t))), sizeof(t)/sizeof((t)[0]), ((void)0))
), "/dev/%s/%u:%u", "block", gnu_dev_major (st.st_dev), gnu_dev_minor
(st.st_dev)) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(t), typeof(&*(t))), sizeof(t)/sizeof((t)[0]), ((void
)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("xsprintf: "
"t" "[] must be big enough"), "../src/shared/bootspec.c", 456
, __PRETTY_FUNCTION__); } while (0)
;
457 errno(*__errno_location ()) = 0;
458 b = blkid_new_probe_from_filename(t);
459 if (!b)
460 return log_error_errno(errno ?: ENOMEM, "Failed to open file system \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 12)),
_realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm
) >= ((_level) & 0x07)) ? log_internal_realm(((_realm)
<< 10 | (_level)), _e, "../src/shared/bootspec.c", 460
, __func__, "Failed to open file system \"%s\": %m", p) : -abs
(_e); })
;
461
462 blkid_probe_enable_superblocks(b, 1);
463 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE(1 << 5));
464 blkid_probe_enable_partitions(b, 1);
465 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS(1 << 2));
466
467 errno(*__errno_location ()) = 0;
468 r = blkid_do_safeprobe(b);
469 if (r == -2) {
470 log_error("File system \"%s\" is ambiguous.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 470, __func__, "File system \"%s\" is ambiguous."
, p) : -abs(_e); })
;
471 return -ENODEV19;
472 } else if (r == 1) {
473 log_error("File system \"%s\" does not contain a label.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 473, __func__, "File system \"%s\" does not contain a label."
, p) : -abs(_e); })
;
474 return -ENODEV19;
475 } else if (r != 0)
476 return log_error_errno(errno ?: EIO, "Failed to probe file system \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 476, __func__
, "Failed to probe file system \"%s\": %m", p) : -abs(_e); })
;
477
478 errno(*__errno_location ()) = 0;
479 r = blkid_probe_lookup_value(b, "TYPE", &v, NULL((void*)0));
480 if (r != 0)
481 return log_error_errno(errno ?: EIO, "Failed to probe file system type \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 481, __func__
, "Failed to probe file system type \"%s\": %m", p) : -abs(_e
); })
;
482 if (!streq(v, "vfat")(strcmp((v),("vfat")) == 0)) {
483 log_error("File system \"%s\" is not FAT.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 483, __func__, "File system \"%s\" is not FAT."
, p) : -abs(_e); })
;
484 return -ENODEV19;
485 }
486
487 errno(*__errno_location ()) = 0;
488 r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL((void*)0));
489 if (r != 0)
490 return log_error_errno(errno ?: EIO, "Failed to probe partition scheme \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 490, __func__
, "Failed to probe partition scheme \"%s\": %m", p) : -abs(_e
); })
;
491 if (!streq(v, "gpt")(strcmp((v),("gpt")) == 0)) {
492 log_error("File system \"%s\" is not on a GPT partition table.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 492, __func__, "File system \"%s\" is not on a GPT partition table."
, p) : -abs(_e); })
;
493 return -ENODEV19;
494 }
495
496 errno(*__errno_location ()) = 0;
497 r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL((void*)0));
498 if (r != 0)
499 return log_error_errno(errno ?: EIO, "Failed to probe partition type UUID \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 499, __func__
, "Failed to probe partition type UUID \"%s\": %m", p) : -abs
(_e); })
;
500 if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")(strcmp((v),("c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) == 0)) {
501 log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 501, __func__, "File system \"%s\" has wrong type for an EFI System Partition (ESP)."
, p) : -abs(_e); })
;
502 return -ENODEV19;
503 }
504
505 errno(*__errno_location ()) = 0;
506 r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL((void*)0));
507 if (r != 0)
508 return log_error_errno(errno ?: EIO, "Failed to probe partition entry UUID \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 508, __func__
, "Failed to probe partition entry UUID \"%s\": %m", p) : -abs
(_e); })
;
509 r = sd_id128_from_string(v, &uuid);
510 if (r < 0) {
511 log_error("Partition \"%s\" has invalid UUID \"%s\".", p, v)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 511, __func__, "Partition \"%s\" has invalid UUID \"%s\"."
, p, v) : -abs(_e); })
;
512 return -EIO5;
513 }
514
515 errno(*__errno_location ()) = 0;
516 r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL((void*)0));
517 if (r != 0)
518 return log_error_errno(errno ?: EIO, "Failed to probe partition number \"%s\": m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 518, __func__
, "Failed to probe partition number \"%s\": m", p) : -abs(_e)
; })
;
519 r = safe_atou32(v, &part);
520 if (r < 0)
521 return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field.")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 521, __func__, "Failed to parse PART_ENTRY_NUMBER field."
) : -abs(_e); })
;
522
523 errno(*__errno_location ()) = 0;
524 r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL((void*)0));
525 if (r != 0)
526 return log_error_errno(errno ?: EIO, "Failed to probe partition offset \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 526, __func__
, "Failed to probe partition offset \"%s\": %m", p) : -abs(_e
); })
;
527 r = safe_atou64(v, &pstart);
528 if (r < 0)
529 return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field.")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 529, __func__, "Failed to parse PART_ENTRY_OFFSET field."
) : -abs(_e); })
;
530
531 errno(*__errno_location ()) = 0;
532 r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL((void*)0));
533 if (r != 0)
534 return log_error_errno(errno ?: EIO, "Failed to probe partition size \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/bootspec.c", 534, __func__
, "Failed to probe partition size \"%s\": %m", p) : -abs(_e);
})
;
535 r = safe_atou64(v, &psize);
536 if (r < 0)
537 return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field.")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/bootspec.c", 537, __func__, "Failed to parse PART_ENTRY_SIZE field."
) : -abs(_e); })
;
538#endif
539
540finish:
541 if (ret_part)
542 *ret_part = part;
543 if (ret_pstart)
544 *ret_pstart = pstart;
545 if (ret_psize)
546 *ret_psize = psize;
547 if (ret_uuid)
548 *ret_uuid = uuid;
549
550 return 0;
551}
552
553int find_esp_and_warn(
554 const char *path,
555 bool_Bool unprivileged_mode,
556 char **ret_path,
557 uint32_t *ret_part,
558 uint64_t *ret_pstart,
559 uint64_t *ret_psize,
560 sd_id128_t *ret_uuid) {
561
562 int r;
563
564 /* This logs about all errors except:
565 *
566 * -ENOKEY → when we can't find the partition
567 * -EACCESS → when unprivileged_mode is true, and we can't access something
568 */
569
570 if (path) {
571 r = verify_esp(path, false0, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid);
572 if (r < 0)
573 return r;
574
575 goto found;
576 }
577
578 FOREACH_STRING(path, "/efi", "/boot", "/boot/efi")for (char **_l = ({ char **_ll = ((char**) ((const char*[]) {
"/efi", "/boot", "/boot/efi", ((void*)0) })); path = _ll ? _ll
[0] : ((void*)0); _ll; }); _l && *_l; path = ({ _l ++
; _l[0]; }))
{
579
580 r = verify_esp(path, true1, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid);
581 if (r >= 0)
582 goto found;
583 if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-2, -99})/sizeof(int)]; switch(r) { case
-2: case -99: _found = 1; break; default: break; } _found; }
)
) /* This one is not it */
584 return r;
585 }
586
587 /* No logging here */
588 return -ENOKEY126;
589
590found:
591 if (ret_path) {
592 char *c;
593
594 c = strdup(path);
595 if (!c)
596 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/shared/bootspec.c"
, 596, __func__)
;
597
598 *ret_path = c;
599 }
600
601 return 0;
602}