1 /* SPDX-License-Identifier: LGPL-2.1+ */
13 #include "alloc-util.h"
14 #include "chattr-util.h"
20 #include "stdio-util.h"
22 #include "time-util.h"
28 /* Reads from efivarfs sometimes fail with EINTR. Retry that many times. */
29 #define EFI_N_RETRIES_NO_DELAY 20
30 #define EFI_N_RETRIES_TOTAL 25
31 #define EFI_RETRY_DELAY (50 * USEC_PER_MSEC)
33 char* efi_variable_path(sd_id128_t vendor
, const char *name
) {
37 "/sys/firmware/efi/efivars/%s-" SD_ID128_UUID_FORMAT_STR
,
38 name
, SD_ID128_FORMAT_VAL(vendor
)) < 0)
44 static char* efi_variable_cache_path(sd_id128_t vendor
, const char *name
) {
48 "/run/systemd/efivars/%s-" SD_ID128_UUID_FORMAT_STR
,
49 name
, SD_ID128_FORMAT_VAL(vendor
)) < 0)
58 uint32_t *ret_attribute
,
62 _cleanup_close_
int fd
= -1;
63 _cleanup_free_
char *p
= NULL
;
64 _cleanup_free_
void *buf
= NULL
;
72 p
= efi_variable_path(vendor
, name
);
76 if (!ret_value
&& !ret_size
&& !ret_attribute
) {
77 /* If caller is not interested in anything, just check if the variable exists and is
79 if (access(p
, R_OK
) < 0)
86 log_debug("Reading EFI variable %s.", p
);
87 begin
= now(CLOCK_MONOTONIC
);
90 fd
= open(p
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
92 return log_debug_errno(errno
, "open(\"%s\") failed: %m", p
);
94 if (fstat(fd
, &st
) < 0)
95 return log_debug_errno(errno
, "fstat(\"%s\") failed: %m", p
);
97 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
), "EFI variable %s is shorter than 4 bytes, refusing.", p
);
98 if (st
.st_size
> 4*1024*1024 + 4)
99 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "EFI variable %s is ridiculously large, refusing.", p
);
101 if (ret_value
|| ret_attribute
) {
102 /* The kernel ratelimits reads from the efivarfs because EFI is inefficient, and we'll
103 * occasionally fail with EINTR here. A slowdown is better than a failure for us, so
104 * retry a few times and eventually fail with -EBUSY.
106 * See https://github.com/torvalds/linux/blob/master/fs/efivarfs/file.c#L75
108 * https://github.com/torvalds/linux/commit/bef3efbeb897b56867e271cdbc5f8adaacaeb9cd.
110 for (unsigned try = 0;; try++) {
111 n
= read(fd
, &a
, sizeof(a
));
114 log_debug_errno(errno
, "Reading from \"%s\" failed: %m", p
);
117 if (try >= EFI_N_RETRIES_TOTAL
)
120 if (try >= EFI_N_RETRIES_NO_DELAY
)
121 (void) usleep(EFI_RETRY_DELAY
);
125 return log_debug_errno(SYNTHETIC_ERRNO(EIO
),
126 "Read %zi bytes from EFI variable %s, expected %zu.", n
, p
, sizeof(a
));
130 buf
= malloc(st
.st_size
- 4 + 3);
134 n
= read(fd
, buf
, (size_t) st
.st_size
- 4);
136 return log_debug_errno(errno
, "Failed to read value of EFI variable %s: %m", p
);
137 assert(n
<= st
.st_size
- 4);
139 /* Always NUL terminate (3 bytes, to properly protect UTF-16, even if truncated in the middle of a character) */
140 ((char*) buf
)[n
] = 0;
141 ((char*) buf
)[n
+ 1] = 0;
142 ((char*) buf
)[n
+ 2] = 0;
144 /* Assume that the reported size is accurate */
148 char ts
[FORMAT_TIMESPAN_MAX
];
151 end
= now(CLOCK_MONOTONIC
);
152 if (end
> begin
+ EFI_RETRY_DELAY
)
153 log_debug("Detected slow EFI variable read access on " SD_ID128_FORMAT_STR
"-%s: %s",
154 SD_ID128_FORMAT_VAL(vendor
), name
, format_timespan(ts
, sizeof(ts
), end
- begin
, 1));
157 /* Note that efivarfs interestingly doesn't require ftruncate() to update an existing EFI variable
158 * with a smaller value. */
164 *ret_value
= TAKE_PTR(buf
);
172 int efi_get_variable_string(sd_id128_t vendor
, const char *name
, char **p
) {
173 _cleanup_free_
void *s
= NULL
;
178 r
= efi_get_variable(vendor
, name
, NULL
, &s
, &ss
);
182 x
= utf16_to_utf8(s
, ss
);
190 int efi_set_variable(
199 } _packed_
* _cleanup_free_ buf
= NULL
;
200 _cleanup_free_
char *p
= NULL
;
201 _cleanup_close_
int fd
= -1;
202 bool saved_flags_valid
= false;
203 unsigned saved_flags
;
207 assert(value
|| size
== 0);
209 p
= efi_variable_path(vendor
, name
);
213 /* Newer efivarfs protects variables that are not in an allow list with FS_IMMUTABLE_FL by default,
214 * to protect them for accidental removal and modification. We are not changing these variables
215 * accidentally however, hence let's unset the bit first. */
217 r
= chattr_path(p
, 0, FS_IMMUTABLE_FL
, &saved_flags
);
218 if (r
< 0 && r
!= -ENOENT
)
219 log_debug_errno(r
, "Failed to drop FS_IMMUTABLE_FL flag from '%s', ignoring: %m", p
);
221 saved_flags_valid
= r
>= 0;
232 fd
= open(p
, O_WRONLY
|O_CREAT
|O_NOCTTY
|O_CLOEXEC
, 0644);
238 buf
= malloc(sizeof(uint32_t) + size
);
244 buf
->attr
= EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
;
245 memcpy(buf
->buf
, value
, size
);
247 r
= loop_write(fd
, buf
, sizeof(uint32_t) + size
, false);
251 /* For some reason efivarfs doesn't update mtime automatically. Let's do it manually then. This is
252 * useful for processes that cache EFI variables to detect when changes occurred. */
253 if (futimens(fd
, (struct timespec
[2]) {
254 { .tv_nsec
= UTIME_NOW
},
255 { .tv_nsec
= UTIME_NOW
}
257 log_debug_errno(errno
, "Failed to update mtime/atime on %s, ignoring: %m", p
);
262 if (saved_flags_valid
) {
265 /* Restore the original flags field, just in case */
267 q
= chattr_path(p
, saved_flags
, FS_IMMUTABLE_FL
, NULL
);
269 q
= chattr_fd(fd
, saved_flags
, FS_IMMUTABLE_FL
, NULL
);
271 log_debug_errno(q
, "Failed to restore FS_IMMUTABLE_FL on '%s', ignoring: %m", p
);
277 int efi_set_variable_string(sd_id128_t vendor
, const char *name
, const char *v
) {
278 _cleanup_free_ char16_t
*u16
= NULL
;
280 u16
= utf8_to_utf16(v
, strlen(v
));
284 return efi_set_variable(vendor
, name
, u16
, (char16_strlen(u16
) + 1) * sizeof(char16_t
));
287 bool is_efi_boot(void) {
288 static int cache
= -1;
291 if (detect_container() > 0)
294 cache
= access("/sys/firmware/efi/", F_OK
) >= 0;
300 static int read_flag(const char *varname
) {
301 _cleanup_free_
void *v
= NULL
;
306 if (!is_efi_boot()) /* If this is not an EFI boot, assume the queried flags are zero */
309 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, varname
, NULL
, &v
, &s
);
320 bool is_efi_secure_boot(void) {
321 static int cache
= -1;
324 cache
= read_flag("SecureBoot");
329 bool is_efi_secure_boot_setup_mode(void) {
330 static int cache
= -1;
333 cache
= read_flag("SetupMode");
338 int cache_efi_options_variable(void) {
339 _cleanup_free_
char *line
= NULL
, *cachepath
= NULL
;
342 /* In SecureBoot mode this is probably not what you want. As your cmdline is cryptographically signed
343 * like when using Type #2 EFI Unified Kernel Images (https://systemd.io/BOOT_LOADER_SPECIFICATION/)
344 * The user's intention is then that the cmdline should not be modified. You want to make sure that
345 * the system starts up as exactly specified in the signed artifact.
347 * (NB: For testing purposes, we still check the $SYSTEMD_EFI_OPTIONS env var before accessing this
348 * cache, even when in SecureBoot mode.) */
349 if (is_efi_secure_boot()) {
350 _cleanup_free_
char *k
;
352 k
= efi_variable_path(EFI_VENDOR_SYSTEMD
, "SystemdOptions");
356 /* Let's be helpful with the returned error and check if the variable exists at all. If it
357 * does, let's return a recognizable error (EPERM), and if not ENODATA. */
359 if (access(k
, F_OK
) < 0)
360 return errno
== ENOENT
? -ENODATA
: -errno
;
365 r
= efi_get_variable_string(EFI_VENDOR_SYSTEMD
, "SystemdOptions", &line
);
371 cachepath
= efi_variable_cache_path(EFI_VENDOR_SYSTEMD
, "SystemdOptions");
375 return write_string_file(cachepath
, line
, WRITE_STRING_FILE_ATOMIC
|WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_MKDIR_0755
);
378 int systemd_efi_options_variable(char **line
) {
380 _cleanup_free_
char *cachepath
= NULL
;
385 /* For testing purposes it is sometimes useful to be able to override this */
386 e
= secure_getenv("SYSTEMD_EFI_OPTIONS");
398 cachepath
= efi_variable_cache_path(EFI_VENDOR_SYSTEMD
, "SystemdOptions");
402 r
= read_one_line_file(cachepath
, line
);