summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier Martinez Canillas <javierm@redhat.com>2021-02-18 12:39:10 +0100
committerPeter Jones <pjones@redhat.com>2021-02-19 14:28:10 -0500
commitea1c872418c4cfa68a11751c7eadd98792aaeecc (patch)
treecb29fe0729283903278b7f6236d68aae7963464a
parent1e78d701accc36a158abb588c8523ac0d4bd248a (diff)
downloadefi-boot-shim-ea1c872418c4cfa68a11751c7eadd98792aaeecc.tar.gz
efi-boot-shim-ea1c872418c4cfa68a11751c7eadd98792aaeecc.zip
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>
-rw-r--r--include/sbat.h3
-rw-r--r--pe.c93
-rw-r--r--sbat.c11
-rw-r--r--shim.c21
4 files changed, 63 insertions, 65 deletions
diff --git a/include/sbat.h b/include/sbat.h
index 94ce01cb..9230b587 100644
--- a/include/sbat.h
+++ b/include/sbat.h
@@ -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
diff --git a/pe.c b/pe.c
index bd974843..dee34725 100644
--- a/pe.c
+++ b/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);
-
- 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;
- }
+ struct sbat_entry **entries = NULL;
+ char *sbat_data;
+ size_t sbat_size;
- 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);
diff --git a/sbat.c b/sbat.c
index a4b75b29..a917b0f8 100644
--- a/sbat.c
+++ b/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;
}
diff --git a/shim.c b/shim.c
index 57b86b19..a7ebaee1 100644
--- a/shim.c
+++ b/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.