mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-06-14 11:10:31 +00:00
Don't re-parse the SBAT EFI variable for each binary we load.
On a typical boot we validate at least two binaries; parsing the SBAT EFI variable each time, when it should not be changing, is not worth the effort. This patch moves the parsing out to some setup code, instead of doing it during the verification stage. Signed-off-by: Peter Jones <pjones@redhat.com>
This commit is contained in:
parent
1e78d701ac
commit
ea1c872418
@ -11,6 +11,7 @@ struct sbat_var {
|
||||
const CHAR8 *component_generation;
|
||||
list_t list;
|
||||
};
|
||||
extern list_t sbat_var;
|
||||
|
||||
EFI_STATUS parse_sbat_var(list_t *entries);
|
||||
void cleanup_sbat_var(list_t *entries);
|
||||
@ -27,7 +28,7 @@ struct sbat_entry {
|
||||
EFI_STATUS parse_sbat(char *sbat_base, size_t sbat_size, size_t *sbats, struct sbat_entry ***sbat);
|
||||
void cleanup_sbat_entries(size_t n, struct sbat_entry **entries);
|
||||
|
||||
EFI_STATUS verify_sbat(size_t n, struct sbat_entry **entries, list_t *var_entries);
|
||||
EFI_STATUS verify_sbat(size_t n, struct sbat_entry **entries);
|
||||
|
||||
#endif /* !SBAT_H_ */
|
||||
// vim:fenc=utf-8:tw=75:noet
|
||||
|
93
pe.c
93
pe.c
@ -1040,67 +1040,49 @@ handle_image (void *data, unsigned int datasize,
|
||||
|
||||
if (secure_mode ()) {
|
||||
unsigned int i;
|
||||
EFI_STATUS efi_status;
|
||||
size_t n;
|
||||
struct sbat_entry **entries;
|
||||
struct sbat_entry *entry = NULL;
|
||||
list_t sbat_var_entries;
|
||||
INIT_LIST_HEAD(&sbat_var_entries);
|
||||
struct sbat_entry **entries = NULL;
|
||||
char *sbat_data;
|
||||
size_t sbat_size;
|
||||
|
||||
if (SBATBase && SBATSize) {
|
||||
char *sbat_data;
|
||||
size_t sbat_size;
|
||||
|
||||
sbat_size = SBATSize + 1;
|
||||
sbat_data = AllocatePool(sbat_size);
|
||||
if (!sbat_data) {
|
||||
console_print(L"Failed to allocate SBAT buffer\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
CopyMem(sbat_data, SBATBase, SBATSize);
|
||||
sbat_data[SBATSize] = '\0';
|
||||
|
||||
efi_status = parse_sbat(sbat_data, sbat_size, &n, &entries);
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
perror(L"SBAT data not correct: %r\n",
|
||||
efi_status);
|
||||
return efi_status;
|
||||
}
|
||||
|
||||
dprint(L"SBAT data\n");
|
||||
for (i = 0; i < n; i++) {
|
||||
entry = entries[i];
|
||||
dprint(L"%a, %a, %a, %a, %a, %a\n",
|
||||
entry->component_name,
|
||||
entry->component_generation,
|
||||
entry->vendor_name,
|
||||
entry->vendor_package_name,
|
||||
entry->vendor_version,
|
||||
entry->vendor_url);
|
||||
}
|
||||
} else {
|
||||
perror(L"SBAT data not found\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
if (SBATBase == NULL || SBATSize == 0) {
|
||||
if (list_empty(&sbat_var))
|
||||
return EFI_SUCCESS;
|
||||
dprint(L"No .sbat section data\n");
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
|
||||
efi_status = parse_sbat_var(&sbat_var_entries);
|
||||
/*
|
||||
* Until a SBAT variable is installed into the systems, it is expected that
|
||||
* attempting to parse the variable will fail with an EFI_NOT_FOUND error.
|
||||
*
|
||||
* Do not consider that error fatal for now.
|
||||
*/
|
||||
if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
|
||||
perror(L"Parsing SBAT variable failed: %r\n",
|
||||
efi_status);
|
||||
sbat_size = SBATSize + 1;
|
||||
sbat_data = AllocatePool(sbat_size);
|
||||
if (!sbat_data) {
|
||||
console_print(L"Failed to allocate .sbat section buffer\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
CopyMem(sbat_data, SBATBase, SBATSize);
|
||||
sbat_data[SBATSize] = '\0';
|
||||
|
||||
efi_status = parse_sbat(sbat_data, sbat_size, &n, &entries);
|
||||
FreePool(sbat_data);
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
perror(L"Could not parse .sbat section data: %r\n", efi_status);
|
||||
return efi_status;
|
||||
}
|
||||
|
||||
if (efi_status == EFI_SUCCESS)
|
||||
efi_status = verify_sbat(n, entries, &sbat_var_entries);
|
||||
if (efi_status == EFI_NOT_FOUND)
|
||||
efi_status = EFI_SUCCESS;
|
||||
dprint(L"SBAT data\n");
|
||||
for (i = 0; i < n; i++) {
|
||||
dprint(L"%a, %a, %a, %a, %a, %a\n",
|
||||
entries[i]->component_name,
|
||||
entries[i]->component_generation,
|
||||
entries[i]->vendor_name,
|
||||
entries[i]->vendor_package_name,
|
||||
entries[i]->vendor_version,
|
||||
entries[i]->vendor_url);
|
||||
}
|
||||
|
||||
efi_status = verify_sbat(n, entries);
|
||||
if (entries)
|
||||
for (i = 0; i < n; i++)
|
||||
FreePool(entries[i]);
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
if (verbose)
|
||||
console_print(L"Verification failed: %r\n", efi_status);
|
||||
@ -1111,11 +1093,6 @@ handle_image (void *data, unsigned int datasize,
|
||||
|
||||
efi_status = verify_buffer(data, datasize,
|
||||
&context, sha256hash, sha1hash);
|
||||
|
||||
if (entries)
|
||||
for (i = 0; i < n; i++)
|
||||
FreePool(entries[i]);
|
||||
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
if (verbose)
|
||||
console_print(L"Verification failed: %r\n", efi_status);
|
||||
|
11
sbat.c
11
sbat.c
@ -194,20 +194,20 @@ cleanup_sbat_var(list_t *entries)
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
verify_sbat(size_t n, struct sbat_entry **entries, list_t *sbat_entries)
|
||||
verify_sbat(size_t n, struct sbat_entry **entries)
|
||||
{
|
||||
unsigned int i;
|
||||
list_t *pos = NULL;
|
||||
EFI_STATUS efi_status = EFI_SUCCESS;
|
||||
struct sbat_var *sbat_var_entry;
|
||||
|
||||
if (!entries || list_empty(sbat_entries)) {
|
||||
dprint(L"SBAT variable not present or malformed\n");
|
||||
return EFI_INVALID_PARAMETER;
|
||||
if (list_empty(&sbat_var)) {
|
||||
dprint(L"SBAT variable not present\n");
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
list_for_each(pos, sbat_entries) {
|
||||
list_for_each(pos, &sbat_var) {
|
||||
sbat_var_entry = list_entry(pos, struct sbat_var, list);
|
||||
efi_status = verify_single_entry(entries[i], sbat_var_entry);
|
||||
if (EFI_ERROR(efi_status))
|
||||
@ -216,7 +216,6 @@ verify_sbat(size_t n, struct sbat_entry **entries, list_t *sbat_entries)
|
||||
}
|
||||
|
||||
dprint(L"all entries from SBAT section verified\n");
|
||||
cleanup_sbat_var(sbat_entries);
|
||||
return efi_status;
|
||||
}
|
||||
|
||||
|
21
shim.c
21
shim.c
@ -43,6 +43,8 @@ static CHAR16 *second_stage;
|
||||
void *load_options;
|
||||
UINT32 load_options_size;
|
||||
|
||||
list_t sbat_var;
|
||||
|
||||
/*
|
||||
* The vendor certificate used for validating the second stage loader
|
||||
*/
|
||||
@ -1751,6 +1753,8 @@ shim_init(void)
|
||||
void
|
||||
shim_fini(void)
|
||||
{
|
||||
cleanup_sbat_var(&sbat_var);
|
||||
|
||||
/*
|
||||
* Remove our protocols
|
||||
*/
|
||||
@ -1853,11 +1857,13 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
|
||||
CHAR16 *msgs[] = {
|
||||
L"import_mok_state() failed",
|
||||
L"shim_init() failed",
|
||||
L"import of SBAT data failed",
|
||||
NULL
|
||||
};
|
||||
enum {
|
||||
IMPORT_MOK_STATE,
|
||||
SHIM_INIT,
|
||||
IMPORT_SBAT,
|
||||
} msg = IMPORT_MOK_STATE;
|
||||
|
||||
/*
|
||||
@ -1888,6 +1894,21 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
|
||||
*/
|
||||
debug_hook();
|
||||
|
||||
INIT_LIST_HEAD(&sbat_var);
|
||||
efi_status = parse_sbat_var(&sbat_var);
|
||||
/*
|
||||
* Until a SBAT variable is installed into the systems, it is expected that
|
||||
* attempting to parse the variable will fail with an EFI_NOT_FOUND error.
|
||||
*
|
||||
* Do not consider that error fatal for now.
|
||||
*/
|
||||
if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
|
||||
perror(L"Parsing SBAT variable failed: %r\n",
|
||||
efi_status);
|
||||
msg = IMPORT_SBAT;
|
||||
goto die;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before we do anything else, validate our non-volatile,
|
||||
* boot-services-only state variables are what we think they are.
|
||||
|
Loading…
Reference in New Issue
Block a user