1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <limits.h>
6 #include <linux/fs.h>
7 #include <stdlib.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10
11 #include "sd-id128.h"
12
13 #include "alloc-util.h"
14 #include "chattr-util.h"
15 #include "efivars.h"
16 #include "fd-util.h"
17 #include "fileio.h"
18 #include "io-util.h"
19 #include "macro.h"
20 #include "memory-util.h"
21 #include "stdio-util.h"
22 #include "strv.h"
23 #include "time-util.h"
24 #include "utf8.h"
25 #include "virt.h"
26
27 #if ENABLE_EFI
28
29 /* Reads from efivarfs sometimes fail with EINTR. Retry that many times. */
30 #define EFI_N_RETRIES_NO_DELAY 20
31 #define EFI_N_RETRIES_TOTAL 25
32 #define EFI_RETRY_DELAY (50 * USEC_PER_MSEC)
33
efi_get_variable(const char * variable,uint32_t * ret_attribute,void ** ret_value,size_t * ret_size)34 int efi_get_variable(
35 const char *variable,
36 uint32_t *ret_attribute,
37 void **ret_value,
38 size_t *ret_size) {
39
40 _cleanup_close_ int fd = -1;
41 _cleanup_free_ void *buf = NULL;
42 struct stat st;
43 usec_t begin = 0; /* Unnecessary initialization to appease gcc */
44 uint32_t a;
45 ssize_t n;
46
47 assert(variable);
48
49 const char *p = strjoina("/sys/firmware/efi/efivars/", variable);
50
51 if (!ret_value && !ret_size && !ret_attribute) {
52 /* If caller is not interested in anything, just check if the variable exists and is
53 * readable. */
54 if (access(p, R_OK) < 0)
55 return -errno;
56
57 return 0;
58 }
59
60 if (DEBUG_LOGGING) {
61 log_debug("Reading EFI variable %s.", p);
62 begin = now(CLOCK_MONOTONIC);
63 }
64
65 fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
66 if (fd < 0)
67 return log_debug_errno(errno, "open(\"%s\") failed: %m", p);
68
69 if (fstat(fd, &st) < 0)
70 return log_debug_errno(errno, "fstat(\"%s\") failed: %m", p);
71 if (st.st_size < 4)
72 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA), "EFI variable %s is shorter than 4 bytes, refusing.", p);
73 if (st.st_size > 4*1024*1024 + 4)
74 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "EFI variable %s is ridiculously large, refusing.", p);
75
76 if (ret_value || ret_attribute) {
77 /* The kernel ratelimits reads from the efivarfs because EFI is inefficient, and we'll
78 * occasionally fail with EINTR here. A slowdown is better than a failure for us, so
79 * retry a few times and eventually fail with -EBUSY.
80 *
81 * See https://github.com/torvalds/linux/blob/master/fs/efivarfs/file.c#L75
82 * and
83 * https://github.com/torvalds/linux/commit/bef3efbeb897b56867e271cdbc5f8adaacaeb9cd.
84 */
85 for (unsigned try = 0;; try++) {
86 n = read(fd, &a, sizeof(a));
87 if (n >= 0)
88 break;
89 log_debug_errno(errno, "Reading from \"%s\" failed: %m", p);
90 if (errno != EINTR)
91 return -errno;
92 if (try >= EFI_N_RETRIES_TOTAL)
93 return -EBUSY;
94
95 if (try >= EFI_N_RETRIES_NO_DELAY)
96 (void) usleep(EFI_RETRY_DELAY);
97 }
98
99 if (n != sizeof(a))
100 return log_debug_errno(SYNTHETIC_ERRNO(EIO),
101 "Read %zi bytes from EFI variable %s, expected %zu.", n, p, sizeof(a));
102 }
103
104 if (ret_value) {
105 buf = malloc(st.st_size - 4 + 3);
106 if (!buf)
107 return -ENOMEM;
108
109 n = read(fd, buf, (size_t) st.st_size - 4);
110 if (n < 0)
111 return log_debug_errno(errno, "Failed to read value of EFI variable %s: %m", p);
112 assert(n <= st.st_size - 4);
113
114 /* Always NUL-terminate (3 bytes, to properly protect UTF-16, even if truncated in the middle
115 * of a character) */
116 ((char*) buf)[n] = 0;
117 ((char*) buf)[n + 1] = 0;
118 ((char*) buf)[n + 2] = 0;
119 } else
120 /* Assume that the reported size is accurate */
121 n = st.st_size - 4;
122
123 if (DEBUG_LOGGING) {
124 usec_t end = now(CLOCK_MONOTONIC);
125 if (end > begin + EFI_RETRY_DELAY)
126 log_debug("Detected slow EFI variable read access on %s: %s",
127 variable, FORMAT_TIMESPAN(end - begin, 1));
128 }
129
130 /* Note that efivarfs interestingly doesn't require ftruncate() to update an existing EFI variable
131 * with a smaller value. */
132
133 if (ret_attribute)
134 *ret_attribute = a;
135
136 if (ret_value)
137 *ret_value = TAKE_PTR(buf);
138
139 if (ret_size)
140 *ret_size = n;
141
142 return 0;
143 }
144
efi_get_variable_string(const char * variable,char ** ret)145 int efi_get_variable_string(const char *variable, char **ret) {
146 _cleanup_free_ void *s = NULL;
147 size_t ss = 0;
148 int r;
149 char *x;
150
151 r = efi_get_variable(variable, NULL, &s, &ss);
152 if (r < 0)
153 return r;
154
155 x = utf16_to_utf8(s, ss);
156 if (!x)
157 return -ENOMEM;
158
159 *ret = x;
160 return 0;
161 }
162
efi_verify_variable(const char * variable,uint32_t attr,const void * value,size_t size)163 static int efi_verify_variable(const char *variable, uint32_t attr, const void *value, size_t size) {
164 _cleanup_free_ void *buf = NULL;
165 size_t n;
166 uint32_t a;
167 int r;
168
169 assert(variable);
170 assert(value || size == 0);
171
172 r = efi_get_variable(variable, &a, &buf, &n);
173 if (r < 0)
174 return r;
175
176 return a == attr && memcmp_nn(buf, n, value, size) == 0;
177 }
178
efi_set_variable(const char * variable,const void * value,size_t size)179 int efi_set_variable(const char *variable, const void *value, size_t size) {
180 struct var {
181 uint32_t attr;
182 char buf[];
183 } _packed_ * _cleanup_free_ buf = NULL;
184 _cleanup_close_ int fd = -1;
185 uint32_t attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
186 bool saved_flags_valid = false;
187 unsigned saved_flags;
188 int r;
189
190 assert(variable);
191 assert(value || size == 0);
192
193 const char *p = strjoina("/sys/firmware/efi/efivars/", variable);
194
195 /* size 0 means removal, empty variable would not be enough for that */
196 if (size > 0 && efi_verify_variable(variable, attr, value, size) > 0) {
197 log_debug("Variable '%s' is already in wanted state, skipping write.", variable);
198 return 0;
199 }
200
201 /* Newer efivarfs protects variables that are not in an allow list with FS_IMMUTABLE_FL by default,
202 * to protect them for accidental removal and modification. We are not changing these variables
203 * accidentally however, hence let's unset the bit first. */
204
205 r = chattr_path(p, 0, FS_IMMUTABLE_FL, &saved_flags);
206 if (r < 0 && r != -ENOENT)
207 log_debug_errno(r, "Failed to drop FS_IMMUTABLE_FL flag from '%s', ignoring: %m", p);
208
209 saved_flags_valid = r >= 0;
210
211 if (size == 0) {
212 if (unlink(p) < 0) {
213 r = -errno;
214 goto finish;
215 }
216
217 return 0;
218 }
219
220 fd = open(p, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0644);
221 if (fd < 0) {
222 r = -errno;
223 goto finish;
224 }
225
226 buf = malloc(sizeof(uint32_t) + size);
227 if (!buf) {
228 r = -ENOMEM;
229 goto finish;
230 }
231
232 buf->attr = attr;
233 memcpy(buf->buf, value, size);
234
235 r = loop_write(fd, buf, sizeof(uint32_t) + size, false);
236 if (r < 0)
237 goto finish;
238
239 /* For some reason efivarfs doesn't update mtime automatically. Let's do it manually then. This is
240 * useful for processes that cache EFI variables to detect when changes occurred. */
241 if (futimens(fd, (struct timespec[2]) {
242 { .tv_nsec = UTIME_NOW },
243 { .tv_nsec = UTIME_NOW }
244 }) < 0)
245 log_debug_errno(errno, "Failed to update mtime/atime on %s, ignoring: %m", p);
246
247 r = 0;
248
249 finish:
250 if (saved_flags_valid) {
251 int q;
252
253 /* Restore the original flags field, just in case */
254 if (fd < 0)
255 q = chattr_path(p, saved_flags, FS_IMMUTABLE_FL, NULL);
256 else
257 q = chattr_fd(fd, saved_flags, FS_IMMUTABLE_FL, NULL);
258 if (q < 0)
259 log_debug_errno(q, "Failed to restore FS_IMMUTABLE_FL on '%s', ignoring: %m", p);
260 }
261
262 return r;
263 }
264
efi_set_variable_string(const char * variable,const char * value)265 int efi_set_variable_string(const char *variable, const char *value) {
266 _cleanup_free_ char16_t *u16 = NULL;
267
268 u16 = utf8_to_utf16(value, strlen(value));
269 if (!u16)
270 return -ENOMEM;
271
272 return efi_set_variable(variable, u16, (char16_strlen(u16) + 1) * sizeof(char16_t));
273 }
274
is_efi_boot(void)275 bool is_efi_boot(void) {
276 static int cache = -1;
277
278 if (cache < 0) {
279 if (detect_container() > 0)
280 cache = false;
281 else {
282 cache = access("/sys/firmware/efi/", F_OK) >= 0;
283 if (!cache && errno != ENOENT)
284 log_debug_errno(errno, "Unable to test whether /sys/firmware/efi/ exists, assuming EFI not available: %m");
285 }
286 }
287
288 return cache;
289 }
290
read_flag(const char * variable)291 static int read_flag(const char *variable) {
292 _cleanup_free_ void *v = NULL;
293 uint8_t b;
294 size_t s;
295 int r;
296
297 if (!is_efi_boot()) /* If this is not an EFI boot, assume the queried flags are zero */
298 return 0;
299
300 r = efi_get_variable(variable, NULL, &v, &s);
301 if (r < 0)
302 return r;
303
304 if (s != 1)
305 return -EINVAL;
306
307 b = *(uint8_t *)v;
308 return !!b;
309 }
310
is_efi_secure_boot(void)311 bool is_efi_secure_boot(void) {
312 static int cache = -1;
313 int r;
314
315 if (cache < 0) {
316 r = read_flag(EFI_GLOBAL_VARIABLE(SecureBoot));
317 if (r == -ENOENT)
318 cache = false;
319 else if (r < 0)
320 log_debug_errno(r, "Error reading SecureBoot EFI variable, assuming not in SecureBoot mode: %m");
321 else
322 cache = r;
323 }
324
325 return cache > 0;
326 }
327
efi_get_secure_boot_mode(void)328 SecureBootMode efi_get_secure_boot_mode(void) {
329 static SecureBootMode cache = _SECURE_BOOT_INVALID;
330
331 if (cache != _SECURE_BOOT_INVALID)
332 return cache;
333
334 int secure = read_flag(EFI_GLOBAL_VARIABLE(SecureBoot));
335 if (secure < 0) {
336 if (secure != -ENOENT)
337 log_debug_errno(secure, "Error reading SecureBoot EFI variable, assuming not in SecureBoot mode: %m");
338
339 return (cache = SECURE_BOOT_UNSUPPORTED);
340 }
341
342 /* We can assume false for all these if they are abscent (AuditMode and
343 * DeployedMode may not exist on older firmware). */
344 int audit = read_flag(EFI_GLOBAL_VARIABLE(AuditMode));
345 int deployed = read_flag(EFI_GLOBAL_VARIABLE(DeployedMode));
346 int setup = read_flag(EFI_GLOBAL_VARIABLE(SetupMode));
347 log_debug("Secure boot variables: SecureBoot=%d AuditMode=%d DeployedMode=%d SetupMode=%d",
348 secure, audit, deployed, setup);
349
350 return (cache = decode_secure_boot_mode(secure, audit > 0, deployed > 0, setup > 0));
351 }
352
read_efi_options_variable(char ** ret)353 static int read_efi_options_variable(char **ret) {
354 int r;
355
356 /* In SecureBoot mode this is probably not what you want. As your cmdline is cryptographically signed
357 * like when using Type #2 EFI Unified Kernel Images (https://systemd.io/BOOT_LOADER_SPECIFICATION)
358 * The user's intention is then that the cmdline should not be modified. You want to make sure that
359 * the system starts up as exactly specified in the signed artifact.
360 *
361 * (NB: For testing purposes, we still check the $SYSTEMD_EFI_OPTIONS env var before accessing this
362 * cache, even when in SecureBoot mode.) */
363 if (is_efi_secure_boot()) {
364 /* Let's be helpful with the returned error and check if the variable exists at all. If it
365 * does, let's return a recognizable error (EPERM), and if not ENODATA. */
366
367 if (access(EFIVAR_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), F_OK) < 0)
368 return errno == ENOENT ? -ENODATA : -errno;
369
370 return -EPERM;
371 }
372
373 r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE(SystemdOptions), ret);
374 if (r == -ENOENT)
375 return -ENODATA;
376 return r;
377 }
378
cache_efi_options_variable(void)379 int cache_efi_options_variable(void) {
380 _cleanup_free_ char *line = NULL;
381 int r;
382
383 r = read_efi_options_variable(&line);
384 if (r < 0)
385 return r;
386
387 return write_string_file(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), line,
388 WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755);
389 }
390
systemd_efi_options_variable(char ** ret)391 int systemd_efi_options_variable(char **ret) {
392 const char *e;
393 int r;
394
395 /* Returns the contents of the variable for current boot from the cache. */
396
397 assert(ret);
398
399 /* For testing purposes it is sometimes useful to be able to override this */
400 e = secure_getenv("SYSTEMD_EFI_OPTIONS");
401 if (e) {
402 char *m;
403
404 m = strdup(e);
405 if (!m)
406 return -ENOMEM;
407
408 *ret = m;
409 return 0;
410 }
411
412 r = read_one_line_file(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), ret);
413 if (r == -ENOENT)
414 return -ENODATA;
415 return r;
416 }
417
compare_stat_mtime(const struct stat * a,const struct stat * b)418 static inline int compare_stat_mtime(const struct stat *a, const struct stat *b) {
419 return CMP(timespec_load(&a->st_mtim), timespec_load(&b->st_mtim));
420 }
421
systemd_efi_options_efivarfs_if_newer(char ** ret)422 int systemd_efi_options_efivarfs_if_newer(char **ret) {
423 struct stat a = {}, b;
424 int r;
425
426 if (stat(EFIVAR_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), &a) < 0 && errno != ENOENT)
427 return log_debug_errno(errno, "Failed to stat EFI variable SystemdOptions: %m");
428
429 if (stat(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), &b) < 0) {
430 if (errno != ENOENT)
431 log_debug_errno(errno, "Failed to stat "EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions))": %m");
432 } else if (compare_stat_mtime(&a, &b) > 0)
433 log_debug("Variable SystemdOptions in evifarfs is newer than in cache.");
434 else {
435 log_debug("Variable SystemdOptions in cache is up to date.");
436 *ret = NULL;
437 return 0;
438 }
439
440 r = read_efi_options_variable(ret);
441 if (r < 0)
442 return log_debug_errno(r, "Failed to read SystemdOptions EFI variable: %m");
443
444 return 0;
445 }
446 #endif
447