]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/boot/bootctl-random-seed.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
5 #include "bootctl-random-seed.h"
6 #include "bootctl-util.h"
13 #include "path-util.h"
14 #include "random-util.h"
15 #include "tmpfile-util.h"
16 #include "umask-util.h"
18 int install_random_seed(const char *esp
) {
19 _cleanup_(unlink_and_freep
) char *tmp
= NULL
;
20 uint8_t buffer
[RANDOM_EFI_SEED_SIZE
];
21 _cleanup_free_
char *path
= NULL
;
22 _cleanup_close_
int fd
= -1;
29 path
= path_join(esp
, "/loader/random-seed");
33 r
= crypto_random_bytes(buffer
, sizeof(buffer
));
35 return log_error_errno(r
, "Failed to acquire random seed: %m");
37 /* Normally create_subdirs() should already have created everything we need, but in case "bootctl
38 * random-seed" is called we want to just create the minimum we need for it, and not the full
40 r
= mkdir_parents(path
, 0755);
42 return log_error_errno(r
, "Failed to create parent directory for %s: %m", path
);
44 r
= tempfn_random(path
, "bootctl", &tmp
);
48 fd
= open(tmp
, O_CREAT
|O_EXCL
|O_NOFOLLOW
|O_NOCTTY
|O_WRONLY
|O_CLOEXEC
, 0600);
51 return log_error_errno(fd
, "Failed to open random seed file for writing: %m");
54 n
= write(fd
, buffer
, sizeof(buffer
));
56 return log_error_errno(errno
, "Failed to write random seed file: %m");
57 if ((size_t) n
!= sizeof(buffer
))
58 return log_error_errno(SYNTHETIC_ERRNO(EIO
), "Short write while writing random seed file.");
60 if (rename(tmp
, path
) < 0)
61 return log_error_errno(r
, "Failed to move random seed file into place: %m");
65 log_info("Random seed file %s successfully written (%zu bytes).", path
, sizeof(buffer
));
67 if (!arg_touch_variables
)
71 log_warning("Acting on %s, skipping EFI variable setup.",
72 arg_image
? "image" : "root directory");
77 log_notice("Not booted with EFI, skipping EFI variable setup.");
81 r
= getenv_bool("SYSTEMD_WRITE_SYSTEM_TOKEN");
84 log_warning_errno(r
, "Failed to parse $SYSTEMD_WRITE_SYSTEM_TOKEN, ignoring.");
86 log_notice("Not writing system token, because $SYSTEMD_WRITE_SYSTEM_TOKEN is set to false.");
90 r
= efi_get_variable(EFI_LOADER_VARIABLE(LoaderSystemToken
), NULL
, NULL
, &token_size
);
92 log_debug_errno(r
, "LoaderSystemToken EFI variable is invalid (too short?), replacing.");
95 return log_error_errno(r
, "Failed to test system token validity: %m");
97 if (token_size
>= sizeof(buffer
)) {
98 /* Let's avoid writes if we can, and initialize this only once. */
99 log_debug("System token already written, not updating.");
103 log_debug("Existing system token size (%zu) does not match our expectations (%zu), replacing.", token_size
, sizeof(buffer
));
106 r
= crypto_random_bytes(buffer
, sizeof(buffer
));
108 return log_error_errno(r
, "Failed to acquire random seed: %m");
110 /* Let's write this variable with an umask in effect, so that unprivileged users can't see the token
111 * and possibly get identification information or too much insight into the kernel's entropy pool
114 r
= efi_set_variable(EFI_LOADER_VARIABLE(LoaderSystemToken
), buffer
, sizeof(buffer
));
117 return log_error_errno(r
, "Failed to write 'LoaderSystemToken' EFI variable: %m");
120 log_warning_errno(r
, "Unable to write 'LoaderSystemToken' EFI variable (firmware problem?), ignoring: %m");
122 log_warning_errno(r
, "Unable to write 'LoaderSystemToken' EFI variable, ignoring: %m");
124 log_info("Successfully initialized system token in EFI variable with %zu bytes.", sizeof(buffer
));
130 int verb_random_seed(int argc
, char *argv
[], void *userdata
) {
133 r
= find_esp_and_warn(arg_root
, arg_esp_path
, false, &arg_esp_path
, NULL
, NULL
, NULL
, NULL
, NULL
);
135 /* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
137 return log_error_errno(r
, "Unable to find ESP.");
139 log_notice("No ESP found, not initializing random seed.");
145 r
= install_random_seed(arg_esp_path
);
149 (void) sync_everything();