mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 08:56:15 +09:00
Merge pull request #23311 from keszybz/bootspec-fuzzer
Fuzzer for bootspec.c and associated fixes
This commit is contained in:
@@ -91,7 +91,12 @@ and generally safe to run on the host without side effects.
|
||||
Ideally, every module in `src/basic/` and `src/shared/` should have a
|
||||
corresponding unit test under `src/test/`, exercising every helper function.
|
||||
|
||||
## Fuzzer test cases
|
||||
## Fuzzing
|
||||
|
||||
Fuzzers are a type of unit tests that execute code on an externally-supplied
|
||||
input sample. Fuzzers are called `fuzz-*`. Fuzzers for `src/basic/` and
|
||||
`src/shared` live under `src/fuzz/`, and those for other parts of the codebase
|
||||
should be located next to the code they test.
|
||||
|
||||
Files under `test/fuzz/` contain input data for fuzzers, one subdirectory for
|
||||
each fuzzer. Some of the files are "seed corpora", i.e. files that contain
|
||||
@@ -102,6 +107,16 @@ When adding new input samples under `test/fuzz/*/`, please use some
|
||||
short-but-meaningful names. Names of meson tests include the input file name
|
||||
and output looks awkward if they are too long.
|
||||
|
||||
Fuzzers are invoked primarily in three ways: firstly, each fuzzer is compiled
|
||||
as a normal executable and executed for each of the input samples under
|
||||
`test/fuzz/` as part of the test suite. Secondly, fuzzers may be instrumented
|
||||
with sanitizers and invoked as part of the test suite (if `-Dfuzz-tests=true`
|
||||
is configured). Thirdly, fuzzers are executed through fuzzing engines that try
|
||||
to find new "interesting" inputs through coverage feedback and massive
|
||||
parallelization; see the links for oss-fuzz in [Code
|
||||
quality](https://systemd.io/CODE_QUALITY). For testing and debugging, fuzzers
|
||||
can be executed as any other program, including under `valgrind` or `gdb`.
|
||||
|
||||
# Integration Tests
|
||||
|
||||
Sources in `test/TEST-*` implement system-level testing for executables,
|
||||
|
||||
@@ -558,39 +558,6 @@ static int status_variables(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int boot_entry_file_check(const char *root, const char *p) {
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
path = path_join(root, p);
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
return RET_NERRNO(access(path, F_OK));
|
||||
}
|
||||
|
||||
static void boot_entry_file_list(const char *field, const char *root, const char *p, int *ret_status) {
|
||||
int status = boot_entry_file_check(root, p);
|
||||
|
||||
printf("%13s%s ", strempty(field), field ? ":" : " ");
|
||||
if (status < 0) {
|
||||
errno = -status;
|
||||
printf("%s%s%s (%m)\n", ansi_highlight_red(), p, ansi_normal());
|
||||
} else
|
||||
printf("%s\n", p);
|
||||
|
||||
if (*ret_status == 0 && status < 0)
|
||||
*ret_status = status;
|
||||
}
|
||||
|
||||
static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = {
|
||||
[BOOT_ENTRY_CONF] = "Boot Loader Specification Type #1 (.conf)",
|
||||
[BOOT_ENTRY_UNIFIED] = "Boot Loader Specification Type #2 (.efi)",
|
||||
[BOOT_ENTRY_LOADER] = "Reported by Boot Loader",
|
||||
[BOOT_ENTRY_LOADER_AUTO] = "Automatic",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType);
|
||||
|
||||
static int boot_config_load_and_select(
|
||||
BootConfig *config,
|
||||
const char *esp_path,
|
||||
@@ -620,104 +587,6 @@ static int boot_config_load_and_select(
|
||||
return boot_config_select_special_entries(config);
|
||||
}
|
||||
|
||||
static int boot_entry_show(
|
||||
const BootEntry *e,
|
||||
bool show_as_default,
|
||||
bool show_as_selected,
|
||||
bool show_reported) {
|
||||
|
||||
int status = 0;
|
||||
|
||||
/* Returns 0 on success, negative on processing error, and positive if something is wrong with the
|
||||
boot entry itself. */
|
||||
|
||||
assert(e);
|
||||
|
||||
printf(" type: %s\n",
|
||||
boot_entry_type_to_string(e->type));
|
||||
|
||||
printf(" title: %s%s%s",
|
||||
ansi_highlight(), boot_entry_title(e), ansi_normal());
|
||||
|
||||
if (show_as_default)
|
||||
printf(" %s(default)%s",
|
||||
ansi_highlight_green(), ansi_normal());
|
||||
|
||||
if (show_as_selected)
|
||||
printf(" %s(selected)%s",
|
||||
ansi_highlight_magenta(), ansi_normal());
|
||||
|
||||
if (show_reported) {
|
||||
if (e->type == BOOT_ENTRY_LOADER)
|
||||
printf(" %s(reported/absent)%s",
|
||||
ansi_highlight_red(), ansi_normal());
|
||||
else if (!e->reported_by_loader && e->type != BOOT_ENTRY_LOADER_AUTO)
|
||||
printf(" %s(not reported/new)%s",
|
||||
ansi_highlight_green(), ansi_normal());
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
|
||||
if (e->id)
|
||||
printf(" id: %s\n", e->id);
|
||||
if (e->path) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
|
||||
/* Let's urlify the link to make it easy to view in an editor, but only if it is a text
|
||||
* file. Unified images are binary ELFs, and EFI variables are not pure text either. */
|
||||
if (e->type == BOOT_ENTRY_CONF)
|
||||
(void) terminal_urlify_path(e->path, NULL, &link);
|
||||
|
||||
printf(" source: %s\n", link ?: e->path);
|
||||
}
|
||||
if (e->sort_key)
|
||||
printf(" sort-key: %s\n", e->sort_key);
|
||||
if (e->version)
|
||||
printf(" version: %s\n", e->version);
|
||||
if (e->machine_id)
|
||||
printf(" machine-id: %s\n", e->machine_id);
|
||||
if (e->architecture)
|
||||
printf(" architecture: %s\n", e->architecture);
|
||||
if (e->kernel)
|
||||
boot_entry_file_list("linux", e->root, e->kernel, &status);
|
||||
|
||||
STRV_FOREACH(s, e->initrd)
|
||||
boot_entry_file_list(s == e->initrd ? "initrd" : NULL,
|
||||
e->root,
|
||||
*s,
|
||||
&status);
|
||||
|
||||
if (!strv_isempty(e->options)) {
|
||||
_cleanup_free_ char *t = NULL, *t2 = NULL;
|
||||
_cleanup_strv_free_ char **ts = NULL;
|
||||
|
||||
t = strv_join(e->options, " ");
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
ts = strv_split_newlines(t);
|
||||
if (!ts)
|
||||
return log_oom();
|
||||
|
||||
t2 = strv_join(ts, "\n ");
|
||||
if (!t2)
|
||||
return log_oom();
|
||||
|
||||
printf(" options: %s\n", t2);
|
||||
}
|
||||
|
||||
if (e->device_tree)
|
||||
boot_entry_file_list("devicetree", e->root, e->device_tree, &status);
|
||||
|
||||
STRV_FOREACH(s, e->device_tree_overlay)
|
||||
boot_entry_file_list(s == e->device_tree_overlay ? "devicetree-overlay" : NULL,
|
||||
e->root,
|
||||
*s,
|
||||
&status);
|
||||
|
||||
return -status;
|
||||
}
|
||||
|
||||
static int status_entries(
|
||||
const BootConfig *config,
|
||||
const char *esp_path,
|
||||
@@ -752,7 +621,7 @@ static int status_entries(
|
||||
else {
|
||||
printf("Default Boot Loader Entry:\n");
|
||||
|
||||
r = boot_entry_show(
|
||||
r = show_boot_entry(
|
||||
boot_config_default_entry(config),
|
||||
/* show_as_default= */ false,
|
||||
/* show_as_selected= */ false,
|
||||
@@ -1861,65 +1730,13 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) {
|
||||
|
||||
pager_open(arg_pager_flags);
|
||||
|
||||
for (size_t i = 0; i < config.n_entries; i++) {
|
||||
_cleanup_free_ char *opts = NULL;
|
||||
BootEntry *e = config.entries + i;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
|
||||
if (!strv_isempty(e->options)) {
|
||||
opts = strv_join(e->options, " ");
|
||||
if (!opts)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_CONDITION(e->id, "id", JSON_BUILD_STRING(e->id)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->path, "path", JSON_BUILD_STRING(e->path)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->root, "root", JSON_BUILD_STRING(e->root)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->title, "title", JSON_BUILD_STRING(e->title)),
|
||||
JSON_BUILD_PAIR_CONDITION(boot_entry_title(e), "showTitle", JSON_BUILD_STRING(boot_entry_title(e))),
|
||||
JSON_BUILD_PAIR_CONDITION(e->sort_key, "sortKey", JSON_BUILD_STRING(e->sort_key)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->version, "version", JSON_BUILD_STRING(e->version)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->machine_id, "machineId", JSON_BUILD_STRING(e->machine_id)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->architecture, "architecture", JSON_BUILD_STRING(e->architecture)),
|
||||
JSON_BUILD_PAIR_CONDITION(opts, "options", JSON_BUILD_STRING(opts)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->kernel, "linux", JSON_BUILD_STRING(e->kernel)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->efi, "efi", JSON_BUILD_STRING(e->efi)),
|
||||
JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->initrd), "initrd", JSON_BUILD_STRV(e->initrd)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->device_tree, "devicetree", JSON_BUILD_STRING(e->device_tree)),
|
||||
JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->device_tree_overlay), "devicetreeOverlay", JSON_BUILD_STRV(e->device_tree_overlay))));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
json_variant_dump(v, arg_json_format_flags, stdout, NULL);
|
||||
}
|
||||
|
||||
} else if (config.n_entries == 0)
|
||||
if (config.n_entries == 0 && FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) {
|
||||
log_info("No boot loader entries found.");
|
||||
else {
|
||||
pager_open(arg_pager_flags);
|
||||
|
||||
printf("Boot Loader Entries:\n");
|
||||
|
||||
for (size_t n = 0; n < config.n_entries; n++) {
|
||||
r = boot_entry_show(
|
||||
config.entries + n,
|
||||
/* show_as_default= */ n == (size_t) config.default_entry,
|
||||
/* show_as_selected= */ n == (size_t) config.selected_entry,
|
||||
/* show_discovered= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (n+1 < config.n_entries)
|
||||
putchar('\n');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
pager_open(arg_pager_flags);
|
||||
return show_boot_entries(&config, arg_json_format_flags);
|
||||
}
|
||||
|
||||
static int install_random_seed(const char *esp) {
|
||||
|
||||
21
src/fuzz/fuzz-bootspec-gen.py
Normal file
21
src/fuzz/fuzz-bootspec-gen.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
"""Generate sample input for fuzz-bootspec"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
config = open(sys.argv[1]).read()
|
||||
loader = [entry for entry in open(sys.argv[2], encoding='utf-16-le').read().split('\0')
|
||||
if len(entry) > 2] # filter out fluff from bad decoding
|
||||
entries = [(os.path.basename(name), open(name).read())
|
||||
for name in sys.argv[3:]]
|
||||
|
||||
data = {
|
||||
'config': config,
|
||||
'entries': entries,
|
||||
'loader': loader,
|
||||
}
|
||||
|
||||
print(json.dumps(data, indent=4))
|
||||
122
src/fuzz/fuzz-bootspec.c
Normal file
122
src/fuzz/fuzz-bootspec.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "bootspec.h"
|
||||
#include "env-util.h"
|
||||
#include "escape.h"
|
||||
#include "fuzz.h"
|
||||
#include "fd-util.h"
|
||||
#include "json.h"
|
||||
|
||||
static int json_dispatch_config(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||||
BootConfig *config = ASSERT_PTR(userdata);
|
||||
|
||||
const char *s = json_variant_string(variant);
|
||||
if (!s)
|
||||
return -EINVAL;
|
||||
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
assert_se(f = data_to_file((const uint8_t*) s, strlen(s)));
|
||||
|
||||
(void) boot_loader_read_conf(config, f, "memstream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_dispatch_entries(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||||
BootConfig *config = ASSERT_PTR(userdata);
|
||||
JsonVariant *entry;
|
||||
|
||||
JSON_VARIANT_ARRAY_FOREACH(entry, variant) {
|
||||
if (!json_variant_is_array(entry) ||
|
||||
json_variant_elements(entry) < 1)
|
||||
return -EINVAL;
|
||||
|
||||
JsonVariant *v;
|
||||
const char *id = NULL, *raw = NULL;
|
||||
_cleanup_free_ char *data = NULL;
|
||||
ssize_t len = -ENODATA;
|
||||
|
||||
v = json_variant_by_index(entry, 0);
|
||||
if (v)
|
||||
id = json_variant_string(v);
|
||||
if (!id)
|
||||
continue;
|
||||
|
||||
v = json_variant_by_index(entry, 1);
|
||||
if (v)
|
||||
raw = json_variant_string(v);
|
||||
if (raw)
|
||||
len = cunescape(raw, UNESCAPE_RELAX | UNESCAPE_ACCEPT_NUL, &data);
|
||||
if (len >= 0) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
assert_se(f = data_to_file((const uint8_t*) data, len));
|
||||
|
||||
assert_se(boot_config_load_type1(config, f, "/", "/entries", id) != -ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_dispatch_loader(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||||
BootConfig *config = ASSERT_PTR(userdata);
|
||||
_cleanup_strv_free_ char **entries = NULL;
|
||||
int r;
|
||||
|
||||
r = json_dispatch_strv(name, variant, flags, &entries);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) boot_config_augment_from_loader(config, entries, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const JsonDispatch data_dispatch[] = {
|
||||
{ "config", JSON_VARIANT_STRING, json_dispatch_config, 0, 0 },
|
||||
{ "entries", JSON_VARIANT_ARRAY, json_dispatch_entries, 0, 0 },
|
||||
{ "loader", JSON_VARIANT_ARRAY, json_dispatch_loader, 0, 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
_cleanup_free_ const char *datadup = NULL;
|
||||
_cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
|
||||
int r;
|
||||
|
||||
/* Disable most logging if not running standalone */
|
||||
if (!getenv("SYSTEMD_LOG_LEVEL"))
|
||||
log_set_max_level(LOG_CRIT);
|
||||
|
||||
assert_se(datadup = memdup_suffix0(data, size));
|
||||
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
r = json_parse(datadup, 0, &v, NULL, NULL);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
r = json_dispatch(v, data_dispatch, NULL, 0, &config);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
assert_se(boot_config_finalize(&config) >= 0);
|
||||
|
||||
(void) boot_config_select_special_entries(&config);
|
||||
|
||||
_cleanup_close_ int orig_stdout_fd = -1;
|
||||
if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) {
|
||||
orig_stdout_fd = fcntl(fileno(stdout), F_DUPFD_CLOEXEC, 3);
|
||||
if (orig_stdout_fd < 0)
|
||||
log_warning_errno(orig_stdout_fd, "Failed to duplicate fd 1: %m");
|
||||
else
|
||||
assert_se(freopen("/dev/null", "w", stdout));
|
||||
}
|
||||
|
||||
(void) show_boot_entries(&config, JSON_FORMAT_OFF);
|
||||
(void) show_boot_entries(&config, JSON_FORMAT_PRETTY);
|
||||
|
||||
if (orig_stdout_fd >= 0)
|
||||
assert_se(freopen(FORMAT_PROC_FD_PATH(orig_stdout_fd), "w", stdout));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,23 +1,25 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
fuzzers += [
|
||||
[files('fuzz-catalog.c')],
|
||||
|
||||
[files('fuzz-json.c')],
|
||||
|
||||
[files('fuzz-varlink.c')],
|
||||
|
||||
[files('fuzz-udev-database.c')],
|
||||
|
||||
[files('fuzz-compress.c')],
|
||||
[files('fuzz-bootspec.c')],
|
||||
|
||||
[files('fuzz-bus-label.c')],
|
||||
|
||||
[files('fuzz-calendarspec.c')],
|
||||
|
||||
[files('fuzz-catalog.c')],
|
||||
|
||||
[files('fuzz-compress.c')],
|
||||
|
||||
[files('fuzz-env-file.c')],
|
||||
|
||||
[files('fuzz-hostname-setup.c')],
|
||||
|
||||
[files('fuzz-calendarspec.c')],
|
||||
[files('fuzz-json.c')],
|
||||
|
||||
[files('fuzz-time-util.c')],
|
||||
|
||||
[files('fuzz-udev-database.c')],
|
||||
|
||||
[files('fuzz-varlink.c')],
|
||||
]
|
||||
|
||||
@@ -2,23 +2,36 @@
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bootspec.h"
|
||||
#include "bootspec-fundamental.h"
|
||||
#include "bootspec.h"
|
||||
#include "conf-files.h"
|
||||
#include "devnum-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "efi-loader.h"
|
||||
#include "env-file.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "find-esp.h"
|
||||
#include "path-util.h"
|
||||
#include "pe-header.h"
|
||||
#include "pretty-print.h"
|
||||
#include "recurse-dir.h"
|
||||
#include "sort-util.h"
|
||||
#include "string-table.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = {
|
||||
[BOOT_ENTRY_CONF] = "Boot Loader Specification Type #1 (.conf)",
|
||||
[BOOT_ENTRY_UNIFIED] = "Boot Loader Specification Type #2 (.efi)",
|
||||
[BOOT_ENTRY_LOADER] = "Reported by Boot Loader",
|
||||
[BOOT_ENTRY_LOADER_AUTO] = "Automatic",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType);
|
||||
|
||||
static void boot_entry_free(BootEntry *entry) {
|
||||
assert(entry);
|
||||
|
||||
@@ -114,6 +127,13 @@ static int boot_entry_load_type1(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isempty(p)) {
|
||||
/* Some fields can reasonably have an empty value. In other cases warn. */
|
||||
if (!STR_IN_SET(field, "options", "devicetree-overlay"))
|
||||
log_warning("%s:%u: Field %s without value", tmp.path, line, field);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (streq(field, "title"))
|
||||
r = free_and_strdup(&tmp.title, p);
|
||||
else if (streq(field, "sort-key"))
|
||||
@@ -155,6 +175,31 @@ static int boot_entry_load_type1(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int boot_config_load_type1(
|
||||
BootConfig *config,
|
||||
FILE *f,
|
||||
const char *root,
|
||||
const char *dir,
|
||||
const char *id) {
|
||||
int r;
|
||||
|
||||
assert(config);
|
||||
assert(f);
|
||||
assert(root);
|
||||
assert(dir);
|
||||
assert(id);
|
||||
|
||||
if (!GREEDY_REALLOC0(config->entries, config->n_entries + 1))
|
||||
return log_oom();
|
||||
|
||||
r = boot_entry_load_type1(f, root, dir, id, config->entries + config->n_entries);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
config->n_entries++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void boot_config_free(BootConfig *config) {
|
||||
assert(config);
|
||||
|
||||
@@ -178,27 +223,19 @@ void boot_config_free(BootConfig *config) {
|
||||
set_free(config->inodes_seen);
|
||||
}
|
||||
|
||||
static int boot_loader_read_conf(const char *path, BootConfig *config) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int boot_loader_read_conf(BootConfig *config, FILE *file, const char *path) {
|
||||
unsigned line = 1;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(config);
|
||||
|
||||
f = fopen(path, "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
|
||||
return log_error_errno(errno, "Failed to open \"%s\": %m", path);
|
||||
}
|
||||
assert(file);
|
||||
assert(path);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *buf = NULL, *field = NULL;
|
||||
const char *p;
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, &buf);
|
||||
r = read_line(file, LONG_LINE_MAX, &buf);
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r == -ENOBUFS)
|
||||
@@ -249,6 +286,23 @@ static int boot_loader_read_conf(const char *path, BootConfig *config) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int boot_loader_read_conf_path(BootConfig *config, const char *path) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
assert(config);
|
||||
assert(path);
|
||||
|
||||
f = fopen(path, "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
|
||||
return log_error_errno(errno, "Failed to open \"%s\": %m", path);
|
||||
}
|
||||
|
||||
return boot_loader_read_conf(config, f, path);
|
||||
}
|
||||
|
||||
static int boot_entry_compare(const BootEntry *a, const BootEntry *b) {
|
||||
int r;
|
||||
|
||||
@@ -375,14 +429,9 @@ static int boot_entries_find_type1(
|
||||
if (r == 0) /* inode already seen or otherwise not relevant */
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC0(config->entries, config->n_entries + 1))
|
||||
return log_oom();
|
||||
|
||||
r = boot_entry_load_type1(f, root, dir, de->d_name, config->entries + config->n_entries);
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
config->n_entries++;
|
||||
r = boot_config_load_type1(config, f, root, dir, de->d_name);
|
||||
if (r == -ENOMEM)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -834,6 +883,18 @@ int boot_config_select_special_entries(BootConfig *config) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int boot_config_finalize(BootConfig *config) {
|
||||
int r;
|
||||
|
||||
typesafe_qsort(config->entries, config->n_entries, boot_entry_compare);
|
||||
|
||||
r = boot_entries_uniquify(config->entries, config->n_entries);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to uniquify boot entries: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int boot_config_load(
|
||||
BootConfig *config,
|
||||
const char *esp_path,
|
||||
@@ -846,7 +907,7 @@ int boot_config_load(
|
||||
|
||||
if (esp_path) {
|
||||
p = strjoina(esp_path, "/loader/loader.conf");
|
||||
r = boot_loader_read_conf(p, config);
|
||||
r = boot_loader_read_conf_path(config, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -873,13 +934,7 @@ int boot_config_load(
|
||||
return r;
|
||||
}
|
||||
|
||||
typesafe_qsort(config->entries, config->n_entries, boot_entry_compare);
|
||||
|
||||
r = boot_entries_uniquify(config->entries, config->n_entries);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to uniquify boot entries: %m");
|
||||
|
||||
return 0;
|
||||
return boot_config_finalize(config);
|
||||
}
|
||||
|
||||
int boot_config_load_auto(
|
||||
@@ -936,6 +991,7 @@ int boot_config_augment_from_loader(
|
||||
"auto-efi-shell", "EFI Shell",
|
||||
"auto-efi-default", "EFI Default Loader",
|
||||
"auto-reboot-to-firmware-setup", "Reboot Into Firmware Interface",
|
||||
NULL,
|
||||
};
|
||||
|
||||
assert(config);
|
||||
@@ -987,6 +1043,16 @@ int boot_config_augment_from_loader(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int boot_entry_file_check(const char *root, const char *p) {
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
path = path_join(root, p);
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
return RET_NERRNO(access(path, F_OK));
|
||||
}
|
||||
|
||||
BootEntry* boot_config_find_entry(BootConfig *config, const char *id) {
|
||||
assert(config);
|
||||
assert(id);
|
||||
@@ -998,3 +1064,172 @@ BootEntry* boot_config_find_entry(BootConfig *config, const char *id) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void boot_entry_file_list(const char *field, const char *root, const char *p, int *ret_status) {
|
||||
int status = boot_entry_file_check(root, p);
|
||||
|
||||
printf("%13s%s ", strempty(field), field ? ":" : " ");
|
||||
if (status < 0) {
|
||||
errno = -status;
|
||||
printf("%s%s%s (%m)\n", ansi_highlight_red(), p, ansi_normal());
|
||||
} else
|
||||
printf("%s\n", p);
|
||||
|
||||
if (*ret_status == 0 && status < 0)
|
||||
*ret_status = status;
|
||||
}
|
||||
|
||||
int show_boot_entry(
|
||||
const BootEntry *e,
|
||||
bool show_as_default,
|
||||
bool show_as_selected,
|
||||
bool show_reported) {
|
||||
|
||||
int status = 0;
|
||||
|
||||
/* Returns 0 on success, negative on processing error, and positive if something is wrong with the
|
||||
boot entry itself. */
|
||||
|
||||
assert(e);
|
||||
|
||||
printf(" type: %s\n",
|
||||
boot_entry_type_to_string(e->type));
|
||||
|
||||
printf(" title: %s%s%s",
|
||||
ansi_highlight(), boot_entry_title(e), ansi_normal());
|
||||
|
||||
if (show_as_default)
|
||||
printf(" %s(default)%s",
|
||||
ansi_highlight_green(), ansi_normal());
|
||||
|
||||
if (show_as_selected)
|
||||
printf(" %s(selected)%s",
|
||||
ansi_highlight_magenta(), ansi_normal());
|
||||
|
||||
if (show_reported) {
|
||||
if (e->type == BOOT_ENTRY_LOADER)
|
||||
printf(" %s(reported/absent)%s",
|
||||
ansi_highlight_red(), ansi_normal());
|
||||
else if (!e->reported_by_loader && e->type != BOOT_ENTRY_LOADER_AUTO)
|
||||
printf(" %s(not reported/new)%s",
|
||||
ansi_highlight_green(), ansi_normal());
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
|
||||
if (e->id)
|
||||
printf(" id: %s\n", e->id);
|
||||
if (e->path) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
|
||||
/* Let's urlify the link to make it easy to view in an editor, but only if it is a text
|
||||
* file. Unified images are binary ELFs, and EFI variables are not pure text either. */
|
||||
if (e->type == BOOT_ENTRY_CONF)
|
||||
(void) terminal_urlify_path(e->path, NULL, &link);
|
||||
|
||||
printf(" source: %s\n", link ?: e->path);
|
||||
}
|
||||
if (e->sort_key)
|
||||
printf(" sort-key: %s\n", e->sort_key);
|
||||
if (e->version)
|
||||
printf(" version: %s\n", e->version);
|
||||
if (e->machine_id)
|
||||
printf(" machine-id: %s\n", e->machine_id);
|
||||
if (e->architecture)
|
||||
printf(" architecture: %s\n", e->architecture);
|
||||
if (e->kernel)
|
||||
boot_entry_file_list("linux", e->root, e->kernel, &status);
|
||||
|
||||
STRV_FOREACH(s, e->initrd)
|
||||
boot_entry_file_list(s == e->initrd ? "initrd" : NULL,
|
||||
e->root,
|
||||
*s,
|
||||
&status);
|
||||
|
||||
if (!strv_isempty(e->options)) {
|
||||
_cleanup_free_ char *t = NULL, *t2 = NULL;
|
||||
_cleanup_strv_free_ char **ts = NULL;
|
||||
|
||||
t = strv_join(e->options, " ");
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
ts = strv_split_newlines(t);
|
||||
if (!ts)
|
||||
return log_oom();
|
||||
|
||||
t2 = strv_join(ts, "\n ");
|
||||
if (!t2)
|
||||
return log_oom();
|
||||
|
||||
printf(" options: %s\n", t2);
|
||||
}
|
||||
|
||||
if (e->device_tree)
|
||||
boot_entry_file_list("devicetree", e->root, e->device_tree, &status);
|
||||
|
||||
STRV_FOREACH(s, e->device_tree_overlay)
|
||||
boot_entry_file_list(s == e->device_tree_overlay ? "devicetree-overlay" : NULL,
|
||||
e->root,
|
||||
*s,
|
||||
&status);
|
||||
|
||||
return -status;
|
||||
}
|
||||
|
||||
int show_boot_entries(const BootConfig *config, JsonFormatFlags json_format) {
|
||||
int r;
|
||||
|
||||
if (!FLAGS_SET(json_format, JSON_FORMAT_OFF)) {
|
||||
for (size_t i = 0; i < config->n_entries; i++) {
|
||||
_cleanup_free_ char *opts = NULL;
|
||||
const BootEntry *e = config->entries + i;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
|
||||
if (!strv_isempty(e->options)) {
|
||||
opts = strv_join(e->options, " ");
|
||||
if (!opts)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_CONDITION(e->id, "id", JSON_BUILD_STRING(e->id)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->path, "path", JSON_BUILD_STRING(e->path)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->root, "root", JSON_BUILD_STRING(e->root)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->title, "title", JSON_BUILD_STRING(e->title)),
|
||||
JSON_BUILD_PAIR_CONDITION(boot_entry_title(e), "showTitle", JSON_BUILD_STRING(boot_entry_title(e))),
|
||||
JSON_BUILD_PAIR_CONDITION(e->sort_key, "sortKey", JSON_BUILD_STRING(e->sort_key)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->version, "version", JSON_BUILD_STRING(e->version)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->machine_id, "machineId", JSON_BUILD_STRING(e->machine_id)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->architecture, "architecture", JSON_BUILD_STRING(e->architecture)),
|
||||
JSON_BUILD_PAIR_CONDITION(opts, "options", JSON_BUILD_STRING(opts)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->kernel, "linux", JSON_BUILD_STRING(e->kernel)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->efi, "efi", JSON_BUILD_STRING(e->efi)),
|
||||
JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->initrd), "initrd", JSON_BUILD_STRV(e->initrd)),
|
||||
JSON_BUILD_PAIR_CONDITION(e->device_tree, "devicetree", JSON_BUILD_STRING(e->device_tree)),
|
||||
JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->device_tree_overlay), "devicetreeOverlay", JSON_BUILD_STRV(e->device_tree_overlay))));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
json_variant_dump(v, json_format, stdout, NULL);
|
||||
}
|
||||
|
||||
} else {
|
||||
printf("Boot Loader Entries:\n");
|
||||
|
||||
for (size_t n = 0; n < config->n_entries; n++) {
|
||||
r = show_boot_entry(
|
||||
config->entries + n,
|
||||
/* show_as_default= */ n == (size_t) config->default_entry,
|
||||
/* show_as_selected= */ n == (size_t) config->selected_entry,
|
||||
/* show_discovered= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (n+1 < config->n_entries)
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "json.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
|
||||
@@ -69,6 +70,8 @@ typedef struct BootConfig {
|
||||
.selected_entry = -1, \
|
||||
}
|
||||
|
||||
const char* boot_entry_type_to_string(BootEntryType);
|
||||
|
||||
BootEntry* boot_config_find_entry(BootConfig *config, const char *id);
|
||||
|
||||
static inline const BootEntry* boot_config_default_entry(const BootConfig *config) {
|
||||
@@ -83,6 +86,16 @@ static inline const BootEntry* boot_config_default_entry(const BootConfig *confi
|
||||
|
||||
void boot_config_free(BootConfig *config);
|
||||
|
||||
int boot_loader_read_conf(BootConfig *config, FILE *file, const char *path);
|
||||
|
||||
int boot_config_load_type1(
|
||||
BootConfig *config,
|
||||
FILE *f,
|
||||
const char *root,
|
||||
const char *dir,
|
||||
const char *id);
|
||||
|
||||
int boot_config_finalize(BootConfig *config);
|
||||
int boot_config_load(BootConfig *config, const char *esp_path, const char *xbootldr_path);
|
||||
int boot_config_load_auto(BootConfig *config, const char *override_esp_path, const char *override_xbootldr_path);
|
||||
int boot_config_augment_from_loader(BootConfig *config, char **list, bool only_auto);
|
||||
@@ -92,5 +105,14 @@ int boot_config_select_special_entries(BootConfig *config);
|
||||
static inline const char* boot_entry_title(const BootEntry *entry) {
|
||||
assert(entry);
|
||||
|
||||
return entry->show_title ?: entry->title ?: entry->id;
|
||||
return ASSERT_PTR(entry->show_title ?: entry->title ?: entry->id);
|
||||
}
|
||||
|
||||
int show_boot_entry(
|
||||
const BootEntry *e,
|
||||
bool show_as_default,
|
||||
bool show_as_selected,
|
||||
bool show_reported);
|
||||
int show_boot_entries(
|
||||
const BootConfig *config,
|
||||
JsonFormatFlags json_format);
|
||||
|
||||
21
test/fuzz/fuzz-bootspec/crash-autoentry
Normal file
21
test/fuzz/fuzz-bootspec/crash-autoentry
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"config": "timeout 3\nconsole-mode 2\n# default 08a5690afeedfeedaaac0a5d2e3cf6b0-*\n# default auto-reboot-to-firmware-setup\n",
|
||||
"entries": [
|
||||
[
|
||||
"08a5690afeedfeedaaac0a5d2e3cf6b0-5.15.14-200.fc35.x86_64.conf",
|
||||
"title Fedora Linux 35 (Workstation Edition)\nversion 5.15.14-200.fc35.x86_64\nmachine-id 08a5690afeedfeedaaac0a5d2e3cf6b0\noptions root=/dev/mapper/fedora_krowka-root rw rd.lvm.lv=fedora_krowka/root rd.luks.uuid=luks-2d9b648a-15b1-4204-988b-ec085089f8ce rd.lvm.lv=fedora_krowka/swap LANG=en_US.UTF-8 selinux=0 resume=/dev/mapper/fedora_krowka-swap systemd.show-status systemd.unit-status-format=name quiet\nlinux /08a5690afeedfeedaaac0a5d2e3cf6b0/5.15.14-200.fc35.x86_64/linux\ninitrd /08a5690afeedfeedaaac0a5d2e3cf6b0/5.15.14-200.fc35.x86_64/initrd\n"
|
||||
],
|
||||
[
|
||||
"08a5690afeedfeedaaac0a5d2e3cf6b0-5.17.0-0.rc5.102.fc36.x86_64.conf",
|
||||
"title Fedora Linux 36 (Workstation Edition Prerelease)\nversion 5.17.0-0.rc5.102.fc36.x86_64\nmachine-id 08a5690afeedfeedaaac0a5d2e3cf6b0\noptions root=/dev/mapper/fedora_krowka-root rw rd.lvm.lv=fedora_krowka/root rd.luks.uuid=luks-2d9b648a-15b1-4204-988b-ec085089f8ce rd.lvm.lv=fedora_krowka/swap LANG=en_US.UTF-8 selinux=0 resume=/dev/mapper/fedora_krowka-swap systemd.show-status systemd.unit-status-format=name quiet\nlinux /08a5690afeedfeedaaac0a5d2e3cf6b0/5.17.0-0.rc5.102.fc36.x86_64/linux\ninitrd /08a5690afeedfeedaaac0a5d2e3cf6b0/5.17.0-0.rc5.102.fc36.x86_64/initrd\n"
|
||||
],
|
||||
[
|
||||
"listing.conf",
|
||||
"title Title\nversion 3.7.2-201.fc18.x86_64\nmachine-id 4098b3f648d74c13b1f04ccfba7798e8\nsort-key 666\nlinux /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux\ninitrd /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd\nefi /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/efi\noptions one two three four\ndevicetree 6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.armv7hl/tegra20-paz00.dtb\ndevicetree-overlay /6a9857a393724b7a981ebb5b8495b9ea/overlays/overlay_A.dtbo /6a9857a393724b7a981ebb5b8495b9ea/overlays/overlay_B.dtbo\narchitecture IA32\narchitecture x64\narchitecture IA64\narchitecture ARM\narchitecture AA64\n"
|
||||
]
|
||||
],
|
||||
"loader": [
|
||||
"08a5690afeedfeedaaac0a5d2e3cf6b0-5.17.0-0.rc5.102.fc36.x86_64.conf",
|
||||
"08a5690afeedfeedaaac0a5d2e3cfkstation Edition Prereleaa_krowse)\nversion 5.17.0-0.rc5.102.fc36.xtup"
|
||||
]
|
||||
}
|
||||
1
test/fuzz/fuzz-bootspec/crash-empty-value
Normal file
1
test/fuzz/fuzz-bootspec/crash-empty-value
Normal file
@@ -0,0 +1 @@
|
||||
{"config": "timeout 3\nconsole-mode 2\n# default 08a5690afeedfeedaaac0a5d2e3cf6b0-*\n# default auto-reboot-to-firmware-set*up\n", "entries": [["08a5690afeedfeedaaac0a5d2e3cf6b0-5.15.14-200.fc35.x86_64.conf", "title Fedora Linux 35 (Workstation Edition)\nversio' 5.15.14-200.fc35.x86_64\nmachine-id 08a5690afeedfeedaaac0a5d2e3cf6b0\noptions root=/dev/mapper/fedora_krowka-root rw rd.lvm.lv=fedora_krowka/root rd.luks.uuid=luks-2d9b648a-15b1-4204-988b-ec085085f8ce rd.lvm.lv=fedora_krowka/swap LANG=en_US.UTF-8 selinux=0 resume='dev/mapper/fedora_krowka-swap systemd.show-status systemd.unit-status-format=name quiet\nlinux /08a5690md.unit-status-format=name quiet\nlinux /08a5690afeedfeedaaac0a5d2e3cf6b0/5.15.14-200.fc35.x86_64/linux\ninitrd /08a5690afeedfeedaaac0a5d2e3cf6b0/5.15.14-200.fc35.x86_64/titled\n"], ["08a5690afeedfeedaaac0a5d2e3cf6b0-5.17.47cf92ac0a5d2e3cf6b0-5.17.0-0.rc5.102.fc36.x86_64.conf", "title Fedora Lin38 6724b7a987ebb5b8495b9ea/3.8.0-2.fc19.armv7hl/tegra20-paz00.dtb\ndevicetree-overlay ", "title Fedora Lin3x 6724b7a987ebb5b8495_64/initrd\n"], ["08a5690afeedfeedaaac0a5d2e3cf6b0-5.17.0-0.rc5.102.fc36.x86_64.conf", "title Fedora Lin3x 6724b7a987ebb5b8495b9ea/3.8.0-2.fc19.armv7hl/tegra20-paz00.dtb\ndevicetree-overlay /6a9857a393'24b7a981ebb5b8495b9ea/overlays/overlay_A.dtbo /6a9857a393724b7a981ebb5b8495b9ea/overlays/overlay_B.dtbo\narchitecture IA32\narchitecture x64\narchitecture IA64\narcetithcure ARM\narchitecture AA64\n"]]}
|
||||
1
test/fuzz/fuzz-bootspec/crash-json-dispatch
Normal file
1
test/fuzz/fuzz-bootspec/crash-json-dispatch
Normal file
@@ -0,0 +1 @@
|
||||
{"config": "timeout ,3\nconsole-mode 2\n#o-firmwapa-setup\n", "entries": [["08a5690afeedfeedaaac0a5d2e3cf6b0-5.15.14mapper/fedod47cf92ac0a\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\3d2e5cf6b0/5.17.0-0.rc5.102.fc3uie4/initrd\n"], ["08a5690afeedfeedaaac0a5d2e3cf6b0-5.17.0-0.rc5.102.86_64/initrd\n"], ["08a5690afeedfeedaaac0a5d2e3cf6b0-5.17.WSL.rc5.102.fc36.x86_64.conf", "title Fedora Lays/overlay_A.dtbo nux /6a9857a393724b7a981eb-15b1-420ition)\nversioedod47cf92ac0a\\\\\\null\\\\\\\\\\\rmv7h)/tegra20-paz00.dtb\ndevicetree-overlay /6/9857a393'24b7a981ebb5ersioedod47cf92ac0a\\\\\\null\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\3d2earchb05/.17.0-0.rc5.102.fc3uiet\nlinux /0iet\nlinux /08a5690afeedfeedaaac0a5d2e3085089fdora Linux 35 (Workstationlirchitecture AA64\n"]]}
|
||||
22
test/fuzz/fuzz-bootspec/sample1
Normal file
22
test/fuzz/fuzz-bootspec/sample1
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"config": "timeout 3\nconsole-mode 2\n# default 08a5690afeedfeedaaac0a5d2e3cf6b0-*\n# default auto-reboot-to-firmware-setup\n",
|
||||
"entries": [
|
||||
[
|
||||
"08a5690afeedfeedaaac0a5d2e3cf6b0-5.15.14-200.fc35.x86_64.conf",
|
||||
"title Fedora Linux 35 (Workstation Edition)\nversion 5.15.14-200.fc35.x86_64\nmachine-id 08a5690afeedfeedaaac0a5d2e3cf6b0\noptions root=/dev/mapper/fedora_krowka-root rw rd.lvm.lv=fedora_krowka/root rd.luks.uuid=luks-2d9b648a-15b1-4204-988b-ec085089f8ce rd.lvm.lv=fedora_krowka/swap LANG=en_US.UTF-8 selinux=0 resume=/dev/mapper/fedora_krowka-swap systemd.show-status systemd.unit-status-format=name quiet\nlinux /08a5690afeedfeedaaac0a5d2e3cf6b0/5.15.14-200.fc35.x86_64/linux\ninitrd /08a5690afeedfeedaaac0a5d2e3cf6b0/5.15.14-200.fc35.x86_64/initrd\n"
|
||||
],
|
||||
[
|
||||
"08a5690afeedfeedaaac0a5d2e3cf6b0-5.17.0-0.rc5.102.fc36.x86_64.conf",
|
||||
"title Fedora Linux 36 (Workstation Edition Prerelease)\nversion 5.17.0-0.rc5.102.fc36.x86_64\nmachine-id 08a5690afeedfeedaaac0a5d2e3cf6b0\noptions root=/dev/mapper/fedora_krowka-root rw rd.lvm.lv=fedora_krowka/root rd.luks.uuid=luks-2d9b648a-15b1-4204-988b-ec085089f8ce rd.lvm.lv=fedora_krowka/swap LANG=en_US.UTF-8 selinux=0 resume=/dev/mapper/fedora_krowka-swap systemd.show-status systemd.unit-status-format=name quiet\nlinux /08a5690afeedfeedaaac0a5d2e3cf6b0/5.17.0-0.rc5.102.fc36.x86_64/linux\ninitrd /08a5690afeedfeedaaac0a5d2e3cf6b0/5.17.0-0.rc5.102.fc36.x86_64/initrd\n"
|
||||
],
|
||||
[
|
||||
"listing.conf",
|
||||
"title Title\nversion 3.7.2-201.fc18.x86_64\nmachine-id 4098b3f648d74c13b1f04ccfba7798e8\nsort-key 666\nlinux /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux\ninitrd /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd\nefi /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/efi\noptions one two three four\ndevicetree 6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.armv7hl/tegra20-paz00.dtb\ndevicetree-overlay /6a9857a393724b7a981ebb5b8495b9ea/overlays/overlay_A.dtbo /6a9857a393724b7a981ebb5b8495b9ea/overlays/overlay_B.dtbo\narchitecture IA32\narchitecture x64\narchitecture IA64\narchitecture ARM\narchitecture AA64\n"
|
||||
]
|
||||
],
|
||||
"loader": [
|
||||
"08a5690a2eed47cf92ac0a5d2e3cf6b0-5.17.0-0.rc5.102.fc36.x86_64.conf",
|
||||
"08a5690a2eed47cf92ac0a5d2e3cf6b0-5.15.14-200.fc35.x86_64.conf",
|
||||
"auto-reboot-to-firmware-setup"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user