summaryrefslogtreecommitdiff
path: root/test-mok-mirror.c
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2025-07-06 21:59:18 +0200
committerChristian Breunig <christian@breunig.cc>2025-07-06 21:59:18 +0200
commit02acad285c74015e8120ade2b41d51b39ae66b63 (patch)
tree980533ac963ac23bc9e090e3e4212bdb9e225a05 /test-mok-mirror.c
parent1c1d50da810e6c49e804a74719c2675b88b033a6 (diff)
parent18d98bfb34be583a5fe2987542e4b15e0db9cb61 (diff)
downloadefi-boot-shim-02acad285c74015e8120ade2b41d51b39ae66b63.tar.gz
efi-boot-shim-02acad285c74015e8120ade2b41d51b39ae66b63.zip
Merge tag '16.0' into vyos/current
shim-16.0 What's Changed * Validate that a supplied vendor cert is not in PEM format by @steve-mcintyre in https://github.com/rhboot/shim/pull/646 * sbat: Add grub.peimage,2 to latest (CVE-2024-2312) by @julian-klode in https://github.com/rhboot/shim/pull/651 * sbat: Also bump latest for grub,4 (and to todays date) by @julian-klode in https://github.com/rhboot/shim/pull/653 * undo change that limits certificate files to a single file by @jsetje in https://github.com/rhboot/shim/pull/659 * shim: don't set second_stage to the empty string by @jjd27 in https://github.com/rhboot/shim/pull/640 * Fix SBAT.md for today's consensus about numbers by @aronowski in https://github.com/rhboot/shim/pull/672 * Update Code of Conduct contact address by @aronowski in https://github.com/rhboot/shim/pull/683 * make-certs: Handle missing OpenSSL installation by @aronowski in https://github.com/rhboot/shim/pull/595 * Update MokVars.txt by @mikebeaton in https://github.com/rhboot/shim/pull/598 * export DEFINES for sub makefile by @bryteise in https://github.com/rhboot/shim/pull/600 * Drop unused EFI_IMAGE_SECURITY_DATABASE_GUID definition by @vittyvk in https://github.com/rhboot/shim/pull/609 * Null-terminate 'arguments' in fallback by @vittyvk in https://github.com/rhboot/shim/pull/611 * Fix "Verifiying" typo in error message by @chrisbainbridge in https://github.com/rhboot/shim/pull/706 * Update Fedora CI targets by @vathpela in https://github.com/rhboot/shim/pull/708 * Force gcc to produce DWARF4 so that gdb can use it by @mikebeaton in https://github.com/rhboot/shim/pull/607 * Minor housekeeping 2024121700 by @vathpela in https://github.com/rhboot/shim/pull/709 * Discard load-options that start with WINDOWS by @Metabolix in https://github.com/rhboot/shim/pull/621 * Fix the issue that the gBS->LoadImage pointer was empty. by @15058718379 in https://github.com/rhboot/shim/pull/703 * shim: Allow data after the end of device path node in load options by @dbnicholson in https://github.com/rhboot/shim/pull/694 * Handle network file not found like disks by @dbnicholson in https://github.com/rhboot/shim/pull/695 * Update gnu-efi submodule for EFI_HTTP_ERROR by @vathpela in https://github.com/rhboot/shim/pull/674 * Increase EFI file alignment by @lumag in https://github.com/rhboot/shim/pull/673 * avoid EFIv2 runtime services on Apple x86 machines by @eduardacatrinei in https://github.com/rhboot/shim/pull/690 * Improve shortcut performance when comparing two boolean expressions by @dennis-tseng99 in https://github.com/rhboot/shim/pull/667 * Provide better error message when MokManager is not found by @rmetrich in https://github.com/rhboot/shim/pull/663 * tpm: Boot with a warning if the event log is full by @kukrimate in https://github.com/rhboot/shim/pull/657 * MokManager: remove redundant logical constraints by @xypron in https://github.com/rhboot/shim/pull/409 * Test import_mok_state() when MokListRT would be bigger than available size by @vathpela in https://github.com/rhboot/shim/pull/417 * test-mok-mirror: minor bug fix by @vathpela in https://github.com/rhboot/shim/pull/715 * Fix file system browser hang when enrolling MOK from disk by @miczyg1 in https://github.com/rhboot/shim/pull/622 * Ignore a minor clang-tidy nit by @vathpela in https://github.com/rhboot/shim/pull/716 * Allow fallback to default loader when encountering errors on network boot by @nathan-omeara in https://github.com/rhboot/shim/pull/666 * test.mk: don't use a temporary random.bin by @vathpela in https://github.com/rhboot/shim/pull/718 * pe: Enhance debug report for update_mem_attrs by @jongwu in https://github.com/rhboot/shim/pull/594 * Multiple certificate handling improvements by @rosslagerwall in https://github.com/rhboot/shim/pull/644 * Generate SbatLevel Metadata from SbatLevel_Variable.txt by @jsetje in https://github.com/rhboot/shim/pull/711 * Apply EKU check with compile option by @dennis-tseng99 in https://github.com/rhboot/shim/pull/664 * Add configuration option to boot an alternative 2nd stage by @esnowberg in https://github.com/rhboot/shim/pull/608 * Loader protocol (with Device Path resolution support) by @kukrimate in https://github.com/rhboot/shim/pull/656 * netboot cleanup for additional files by @jsetje in https://github.com/rhboot/shim/pull/686 * Document how revocations can be delivered by @jsetje in https://github.com/rhboot/shim/pull/722 * post-process-pe: add tests to validate NX compliance by @vathpela in https://github.com/rhboot/shim/pull/705 * regression: CopyMem() in ad8692e copies out of bounds by @jsetje in https://github.com/rhboot/shim/pull/725 * Save the debug and error logs in mok-variables by @vathpela in https://github.com/rhboot/shim/pull/726 * Add features for the Host Security ID program by @vathpela in https://github.com/rhboot/shim/pull/660 * Mirror some more efi variables to mok-variables by @vathpela in https://github.com/rhboot/shim/pull/723 * This adds DXE Services measurements to HSI and uses them for NX by @vathpela in https://github.com/rhboot/shim/pull/724 * Add shim's current NX_COMPAT status to HSIStatus by @vathpela in https://github.com/rhboot/shim/pull/727 * README.tpm: reflect that vendor_db is in fact logged as "vendor_db" by @jsetje in https://github.com/rhboot/shim/pull/728 * Reject HTTP message with duplicate Content-Length header fields by @dennis-tseng99 in https://github.com/rhboot/shim/pull/637 * Disable log saving by @vathpela in https://github.com/rhboot/shim/pull/729 * fallback: don't add new boot order entries backwards by @vathpela in https://github.com/rhboot/shim/pull/730 * Misc fixes... by @vathpela in https://github.com/rhboot/shim/pull/735 * README.tpm: Update MokList entry to MokListRT by @trungams in https://github.com/rhboot/shim/pull/732 * SBAT Level update for February 2025 GRUB CVEs by @jsetje in https://github.com/rhboot/shim/pull/736 New Contributors * @jjd27 made their first contribution in https://github.com/rhboot/shim/pull/640 * @mikebeaton made their first contribution in https://github.com/rhboot/shim/pull/598 * @bryteise made their first contribution in https://github.com/rhboot/shim/pull/600 * @vittyvk made their first contribution in https://github.com/rhboot/shim/pull/609 * @chrisbainbridge made their first contribution in https://github.com/rhboot/shim/pull/706 * @Metabolix made their first contribution in https://github.com/rhboot/shim/pull/621 * @15058718379 made their first contribution in https://github.com/rhboot/shim/pull/703 * @dbnicholson made their first contribution in https://github.com/rhboot/shim/pull/694 * @lumag made their first contribution in https://github.com/rhboot/shim/pull/673 * @eduardacatrinei made their first contribution in https://github.com/rhboot/shim/pull/690 * @kukrimate made their first contribution in https://github.com/rhboot/shim/pull/657 * @miczyg1 made their first contribution in https://github.com/rhboot/shim/pull/622 * @nathan-omeara made their first contribution in https://github.com/rhboot/shim/pull/666 * @jongwu made their first contribution in https://github.com/rhboot/shim/pull/594 * @rosslagerwall made their first contribution in https://github.com/rhboot/shim/pull/644 * @trungams made their first contribution in https://github.com/rhboot/shim/pull/732 **Full Changelog**: https://github.com/rhboot/shim/compare/15.8...16.0 * tag '16.0': (451 commits) Update version to 16.0 SBAT Level update for February 2025 GRUB CVEs README.tpm: Update MokList entry to MokListRT Make 'make fanalyzer' work again. simple_dir_filter(): test our 'next' pointer shim_load_image(): initialize the buffer fully mirror_mok_db(): Free our mok variable name correctly mirror_one_mok_variable(): fix a memory leak on TPM log error. mirror_mok_db(): get rid of an unused variable+allocation generate_sbat_var_defs: Ensure revlistentry->revocations is initialized. generate_sbat_var_defs: Fix memory leak on realloc failure and fd leak. generate_sbat_var_defs: run clang-format on readfile() SetSecureVariable(): free Cert on failure Update version to 16.0~rc1 make-archive: some minor housekeeping makefiles: Make GITTAG swizzle tildes to dashes fallback: don't add new boot order entries backwards Disable log saving for now. Some save_logs() improvements. reject message with different values in multiple Content-Length header field ...
Diffstat (limited to 'test-mok-mirror.c')
-rw-r--r--test-mok-mirror.c575
1 files changed, 445 insertions, 130 deletions
diff --git a/test-mok-mirror.c b/test-mok-mirror.c
index f34f62a9..38b7ed97 100644
--- a/test-mok-mirror.c
+++ b/test-mok-mirror.c
@@ -8,6 +8,7 @@
#include "mock-variables.h"
#include "test-data-efivars-1.h"
+#include <err.h>
#include <stdio.h>
#pragma GCC diagnostic ignored "-Wunused-parameter"
@@ -21,21 +22,51 @@ start_image(EFI_HANDLE image_handle UNUSED, CHAR16 *mm)
#define N_TEST_VAR_OPS 40
struct test_var {
+ /*
+ * The GUID, name, and attributes of the variables
+ */
EFI_GUID guid;
CHAR16 *name;
UINT32 attrs;
- UINTN n_ops;
+ /*
+ * If the variable is required to be present, with the attributes
+ * specified above, for a test to pass
+ */
bool must_be_present;
+ /*
+ * If the variable is required to be absent, no matter what the
+ * attributes, for a test to pass
+ */
bool must_be_absent;
+ /*
+ * The number of operations on this variable that we've seen
+ */
+ UINTN n_ops;
+ /*
+ * the operations that have occurred on this variable
+ */
mock_variable_op_t ops[N_TEST_VAR_OPS];
+ /*
+ * the result codes of those operations
+ */
EFI_STATUS results[N_TEST_VAR_OPS];
};
static struct test_var *test_vars;
struct mock_mok_variable_config_entry {
+ /*
+ * The name of an entry we expect to see in the MokVars
+ * configuration table
+ */
CHAR8 name[256];
+ /*
+ * The size of its data
+ */
UINT64 data_size;
+ /*
+ * A pointer to what the data should be
+ */
const unsigned char *data;
};
@@ -94,16 +125,217 @@ getvar_post(CHAR16 *name, EFI_GUID *guid,
}
}
+static EFI_STATUS
+check_variables(struct test_var *vars)
+{
+ for (size_t i = 0; vars[i].name != NULL; i++) {
+ struct test_var *tv = &vars[i];
+ list_t *pos = NULL;
+ bool found = false;
+ char buf[1];
+ UINTN size = 0;
+ UINT32 attrs = 0;
+ bool present = false;
+
+ list_for_each(pos, &mock_variables) {
+ struct mock_variable *var;
+ bool deleted;
+ bool created;
+ int gets = 0;
+
+ var = list_entry(pos, struct mock_variable, list);
+ if (CompareGuid(&tv->guid, &var->guid) != 0 ||
+ StrCmp(var->name, tv->name) != 0)
+ continue;
+ found = true;
+ assert_equal_goto(var->attrs, tv->attrs, err,
+ "\"%s\": wrong attrs; got %s expected %s\n",
+ Str2str(tv->name),
+ format_var_attrs(var->attrs),
+ format_var_attrs(tv->attrs));
+ for (UINTN j = 0; j < N_TEST_VAR_OPS
+ && tv->ops[j] != NONE; j++) {
+ switch (tv->ops[j]) {
+ case NONE:
+ default:
+ break;
+ case CREATE:
+ if (tv->results[j] == EFI_SUCCESS)
+ created = true;
+ break;
+ case DELETE:
+ assert_goto(tv->results[j] != EFI_SUCCESS, err,
+ "Tried to delete absent variable \"%s\"\n",
+ Str2str(tv->name));
+ assert_goto(created == false, err,
+ "Deleted variable \"%s\" was previously created.\n",
+ Str2str(tv->name));
+ break;
+ case APPEND:
+ assert_goto(false, err,
+ "No append action should have been tested\n");
+ break;
+ case REPLACE:
+ assert_goto(false, err,
+ "No replace action should have been tested\n");
+ break;
+ case GET:
+ if (tv->results[j] == EFI_SUCCESS)
+ gets += 1;
+ break;
+ }
+ }
+ assert_goto(gets == 0 || gets == 1, err,
+ "Variable should not be read %d times.\n", gets);
+ }
+ if (tv->must_be_present) {
+ /*
+ * This asserts if it isn't present, and if that's
+ * the case, then the attributes are already
+ * validated in the search loop
+ */
+ assert_goto(found == true, err,
+ "variable \"%s\" was not found.\n",
+ Str2str(tv->name));
+ }
+
+ if (tv->must_be_absent) {
+ /*
+ * deliberately does not check the attributes at
+ * this time.
+ */
+ assert_goto(found == false, err,
+ "variable \"%s\" was found.\n",
+ Str2str(tv->name));
+ }
+ }
+
+ return EFI_SUCCESS;
+err:
+ return EFI_INVALID_PARAMETER;
+}
+
+static EFI_STATUS
+check_config_table(struct mock_mok_variable_config_entry *test_configs,
+ uint8_t *config_pos)
+{
+ size_t i = 0;
+ struct mok_variable_config_entry *mok_entry = NULL;
+ struct mock_mok_variable_config_entry *mock_entry = NULL;
+
+ while (config_pos) {
+ mock_entry = &test_configs[i];
+ mok_entry = (struct mok_variable_config_entry *)config_pos;
+
+ /*
+ * If the tables are different lengths, this will trigger.
+ */
+ assert_equal_goto(mok_entry->name[0], mock_entry->name[0], err,
+ "mok.name[0] %ld != test.name[0] %ld\n");
+ if (mock_entry->name[0] == 0)
+ break;
+
+ assert_nonzero_goto(mok_entry->name[0], err, "%ld != %ld\n");
+ assert_zero_goto(strncmp(mok_entry->name, mock_entry->name,
+ sizeof(mock_entry->name)),
+ err, "%ld != %ld: strcmp(\"%s\",\"%s\")\n",
+ mok_entry->name, mock_entry->name);
+
+ /*
+ * As of 7501b6bb449f ("mok: fix potential buffer overrun in
+ * import_mok_state"), we should not see any mok config
+ * variables with data_size == 0.
+ */
+ assert_nonzero_goto(mok_entry->data_size, err, "%ld != 0\n");
+
+ assert_equal_goto(mok_entry->data_size, mock_entry->data_size,
+ err, "%ld != %ld\n");
+ assert_zero_goto(CompareMem(mok_entry->data, mock_entry->data,
+ mok_entry->data_size),
+ err, "%ld != %ld\n");
+ config_pos += offsetof(struct mok_variable_config_entry, data)
+ + mok_entry->data_size;
+ i += 1;
+ }
+
+ return EFI_SUCCESS;
+err:
+ warnx("Failed on entry %zu mok.name:\"%s\" mock.name:\"%s\"", i,
+ mok_entry->name, mock_entry->name);
+ if ((mok_entry && mock_entry) && (!mok_entry->name[0] || !mock_entry->name[0]))
+ warnx("Entry is missing in %s variable list.", mok_entry->name[0] ? "expected" : "found");
+
+ return EFI_INVALID_PARAMETER;
+}
+
+static int
+test_mok_mirror(struct test_var *vars,
+ struct mock_mok_variable_config_entry *configs,
+ EFI_STATUS expected_status)
+{
+ EFI_STATUS status;
+ EFI_GUID mok_config_guid = MOK_VARIABLE_STORE;
+ int ret = -1;
+
+ status = import_mok_state(NULL);
+ assert_equal_goto(status, expected_status, err,
+ "got 0x%016lx, expected 0x%016lx\n",
+ expected_status);
+
+ test_vars = vars;
+
+ status = check_variables(vars);
+ if (EFI_ERROR(status))
+ goto err;
+
+ uint8_t *pos = NULL;
+ for (size_t i = 0; i < ST->NumberOfTableEntries; i++) {
+ EFI_CONFIGURATION_TABLE *ct = &ST->ConfigurationTable[i];
+
+ if (CompareGuid(&ct->VendorGuid, &mok_config_guid) != 0)
+ continue;
+
+ pos = (void *)ct->VendorTable;
+ break;
+ }
+
+ assert_nonzero_goto(pos, err, "%p != 0\n");
+
+ status = check_config_table(configs, pos);
+ if (EFI_ERROR(status))
+ goto err;
+
+ ret = 0;
+err:
+ for (UINTN k = 0; k < n_mok_state_variables; k++) {
+ struct mok_state_variable *v =
+ &mok_state_variables[k];
+ if (v->data_size && v->data) {
+ free(v->data);
+ v->data = NULL;
+ v->data_size = 0;
+ }
+ }
+
+ test_vars = NULL;
+
+ return ret;
+}
+
+/*
+ * This tests mirroring of mok variables on fairly optimistic conditions:
+ * there's enough space for everything, and so we expect to see all the
+ * RT variables for which we have data mirrored
+ */
static int
-test_mok_mirror_0(void)
+test_mok_mirror_with_enough_space(void)
{
const char *mok_rt_vars[n_mok_state_variables];
EFI_STATUS status;
EFI_GUID guid = SHIM_LOCK_GUID;
- EFI_GUID mok_config_guid = MOK_VARIABLE_STORE;
int ret = -1;
- struct test_var test_mok_mirror_0_vars[] = {
+ struct test_var test_mok_mirror_with_enough_space_vars[] = {
{.guid = SHIM_LOCK_GUID,
.name = L"MokList",
.must_be_present = true,
@@ -166,11 +398,20 @@ test_mok_mirror_0(void)
EFI_VARIABLE_RUNTIME_ACCESS,
.ops = { NONE, },
},
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"HSIStatus",
+ .attrs = 0,
+ .ops = { NONE, },
+ },
{.guid = { 0, },
.name = NULL,
}
};
+ /*
+ * We must see the supplied values of MokListRT, MokListXRT, and
+ * SbatLevelRT in the config table
+ */
struct mock_mok_variable_config_entry test_mok_config_table[] = {
{.name = "MokListRT",
.data_size = sizeof(test_data_efivars_1_MokListRT),
@@ -188,6 +429,10 @@ test_mok_mirror_0(void)
.data_size = sizeof(test_data_efivars_1_MokListTrustedRT),
.data = test_data_efivars_1_MokListTrustedRT
},
+ {.name = "HSIStatus",
+ .data_size = sizeof(test_data_efivars_1_HSIStatus),
+ .data = test_data_efivars_1_HSIStatus
+ },
{.name = { 0, },
.data_size = 0,
.data = NULL,
@@ -202,147 +447,214 @@ test_mok_mirror_0(void)
mock_set_variable_post_hook = setvar_post;
mock_get_variable_post_hook = getvar_post;
- test_vars = &test_mok_mirror_0_vars[0];
- import_mok_state(NULL);
+ ret = test_mok_mirror(&test_mok_mirror_with_enough_space_vars[0],
+ test_mok_config_table,
+ EFI_SUCCESS);
- for (size_t i = 0; test_mok_mirror_0_vars[i].name != NULL; i++) {
- struct test_var *tv = &test_mok_mirror_0_vars[i];
- list_t *pos = NULL;
- bool found = false;
- char buf[1];
- UINTN size = 0;
- UINT32 attrs = 0;
- bool present = false;
+ mock_set_variable_post_hook = NULL;
+ mock_get_variable_post_hook = NULL;
+ return ret;
+}
- list_for_each(pos, &mock_variables) {
- struct mock_variable *var;
- bool deleted;
- bool created;
- int gets = 0;
+static int
+test_mok_mirror_setvar_out_of_resources(void)
+{
+ const char *mok_rt_vars[n_mok_state_variables];
+ EFI_STATUS status;
+ EFI_GUID guid = SHIM_LOCK_GUID;
+ EFI_GUID mok_config_guid = MOK_VARIABLE_STORE;
+ int ret = -1;
- var = list_entry(pos, struct mock_variable, list);
- if (CompareGuid(&tv->guid, &var->guid) != 0 ||
- StrCmp(var->name, tv->name) != 0)
- continue;
- found = true;
- assert_equal_goto(var->attrs, tv->attrs, err,
- "\"%s\": wrong attrs; got %s expected %s\n",
- Str2str(tv->name),
- format_var_attrs(var->attrs),
- format_var_attrs(tv->attrs));
- for (UINTN j = 0; j < N_TEST_VAR_OPS
- && tv->ops[j] != NONE; j++) {
- switch (tv->ops[j]) {
- case NONE:
- default:
- break;
- case CREATE:
- if (tv->results[j] == EFI_SUCCESS)
- created = true;
- break;
- case DELETE:
- assert_goto(tv->results[j] != EFI_SUCCESS, err,
- "Tried to delete absent variable \"%s\"\n",
- Str2str(tv->name));
- assert_goto(created == false, err,
- "Deleted variable \"%s\" was previously created.\n",
- Str2str(tv->name));
- break;
- case APPEND:
- assert_goto(false, err,
- "No append action should have been tested\n");
- break;
- case REPLACE:
- assert_goto(false, err,
- "No replace action should have been tested\n");
- break;
- case GET:
- if (tv->results[j] == EFI_SUCCESS)
- gets += 1;
- break;
- }
- }
- assert_goto(gets == 0 || gets == 1, err,
- "Variable should not be read %d times.\n", gets);
- }
- if (tv->must_be_present) {
- assert_goto(found == true, err,
- "variable \"%s\" was not found.\n",
- Str2str(tv->name));
- }
+ /*
+ * These sizes are picked specifically so that MokListRT will fail
+ * to get mirrored with the test data in test-data/efivars-1
+ */
+ list_t mock_obnoxious_variable_limits;
+ UINT64 obnoxious_max_var_storage = 0xffe4;
+ UINT64 obnoxious_remaining_var_storage = 919+0x3c;
+ UINT64 obnoxious_max_var_size = 919;
+
+ struct mock_variable_limits obnoxious_limits[] = {
+ {.attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ .max_var_storage = &obnoxious_max_var_storage,
+ .remaining_var_storage = &obnoxious_remaining_var_storage,
+ .max_var_size = &obnoxious_max_var_size,
+ .status = EFI_SUCCESS,
+ },
+ {.attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ .max_var_storage = &obnoxious_max_var_storage,
+ .remaining_var_storage = &obnoxious_remaining_var_storage,
+ .max_var_size = &obnoxious_max_var_size,
+ .status = EFI_SUCCESS,
+ },
+ {.attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE,
+ .max_var_storage = &obnoxious_max_var_storage,
+ .remaining_var_storage = &obnoxious_remaining_var_storage,
+ .max_var_size = &obnoxious_max_var_size,
+ .status = EFI_SUCCESS,
+ },
+ {.attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE,
+ .max_var_storage = &obnoxious_max_var_storage,
+ .remaining_var_storage = &obnoxious_remaining_var_storage,
+ .max_var_size = &obnoxious_max_var_size,
+ .status = EFI_SUCCESS,
+ },
+ {.attrs = 0, }
+ };
- if (tv->must_be_absent) {
- assert_goto(found == false, err,
- "variable \"%s\" was found.\n",
- Str2str(tv->name));
+ struct test_var test_mok_mirror_enospc_vars[] = {
+ /*
+ * We must to see a BS|NV MokList
+ */
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"MokList",
+ .must_be_present = true,
+ .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE,
+ .ops = { NONE, },
+ },
+ /*
+ * We must *NOT* see a BS|RT MokListRT
+ */
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"MokListRT",
+ .must_be_absent = true,
+ .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ .ops = { NONE, },
+ },
+ /*
+ * We must see a BS|NV MokListX
+ */
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"MokListX",
+ .must_be_present = true,
+ .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE,
+ .ops = { NONE, },
+ },
+ /*
+ * We must see a BS|RT MokListXRT
+ */
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"MokListXRT",
+ .must_be_present = true,
+ .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ .ops = { NONE, },
+ },
+ /*
+ * We must see a BS|NV SbatLevel
+ */
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"SbatLevel",
+ .must_be_present = true,
+ .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE,
+ .ops = { NONE, },
+ },
+ /*
+ * We must see a BS|RT SbatLevelRT
+ */
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"SbatLevelRT",
+ .must_be_present = true,
+ .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ .ops = { NONE, },
+ },
+ /*
+ * We must not see a MokIgnoreDB
+ */
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"MokIgnoreDB",
+ .must_be_absent = true,
+ .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ .ops = { NONE, },
+ },
+ /*
+ * We must not see MokSBState
+ */
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"MokSBState",
+ .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE,
+ .ops = { NONE, },
+ },
+ /*
+ * We must not see MokSBStateRT
+ */
+ {.guid = SHIM_LOCK_GUID,
+ .name = L"MokSBStateRT",
+ .must_be_absent = true,
+ .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ .ops = { NONE, },
+ },
+ {.guid = { 0, },
+ .name = NULL,
}
- }
+ };
- uint8_t *pos = NULL;
- for (size_t i = 0; i < ST->NumberOfTableEntries; i++) {
- EFI_CONFIGURATION_TABLE *ct = &ST->ConfigurationTable[i];
+ /*
+ * We must see the supplied values of MokListRT, MokListXRT, and
+ * SbatLevelRT in the config table
+ */
+ struct mock_mok_variable_config_entry test_mok_config_table[] = {
+ {.name = "MokListRT",
+ .data_size = sizeof(test_data_efivars_1_MokListRT),
+ .data = test_data_efivars_1_MokListRT
+ },
+ {.name = "MokListXRT",
+ .data_size = sizeof(test_data_efivars_1_MokListXRT),
+ .data = test_data_efivars_1_MokListXRT
+ },
+ {.name = "SbatLevelRT",
+ .data_size = sizeof(test_data_efivars_1_SbatLevelRT),
+ .data = test_data_efivars_1_SbatLevelRT
+ },
+ {.name = "MokListTrustedRT",
+ .data_size = sizeof(test_data_efivars_1_MokListTrustedRT),
+ .data = test_data_efivars_1_MokListTrustedRT
+ },
+ {.name = "HSIStatus",
+ .data_size = sizeof(test_data_efivars_1_HSIStatus),
+ .data = test_data_efivars_1_HSIStatus
+ },
+ {.name = { 0, },
+ .data_size = 0,
+ .data = NULL,
+ }
+ };
- if (CompareGuid(&ct->VendorGuid, &mok_config_guid) != 0)
- continue;
+ UINT64 max_storage_sz = 0;
+ UINT64 max_var_sz = 0;
+ UINT64 remaining_sz = 0;
- pos = (void *)ct->VendorTable;
- break;
+ for (size_t i = 0; i < n_mok_state_variables; i++) {
+ mok_rt_vars[i] = mok_state_variables[i].rtname8;
}
- assert_nonzero_goto(pos, err, "%p != 0\n");
+ mock_load_variables("test-data/efivars-1", mok_rt_vars, true);
- size_t i = 0;
- while (pos) {
- struct mock_mok_variable_config_entry *mock_entry =
- &test_mok_config_table[i];
- struct mok_variable_config_entry *mok_entry =
- (struct mok_variable_config_entry *)pos;
+ mock_set_variable_post_hook = setvar_post;
+ mock_get_variable_post_hook = getvar_post;
- /*
- * If the tables are different lengths, this will trigger.
- */
- assert_equal_goto(mok_entry->name[0], mock_entry->name[0], err,
- "mok.name[0] %ld != test.name[0] %ld\n");
- if (mock_entry->name[0] == 0)
- break;
+ mock_set_usage_limits(&mock_obnoxious_variable_limits,
+ &obnoxious_limits[0]);
- assert_nonzero_goto(mok_entry->name[0], err, "%ld != %ld\n");
- assert_zero_goto(strncmp(mok_entry->name, mock_entry->name,
- sizeof(mock_entry->name)),
- err, "%ld != %ld: strcmp(\"%s\",\"%s\")\n",
- mok_entry->name, mock_entry->name);
+ ret = test_mok_mirror(&test_mok_mirror_enospc_vars[0],
+ test_mok_config_table,
+ EFI_OUT_OF_RESOURCES);
- /*
- * As of 7501b6bb449f ("mok: fix potential buffer overrun in
- * import_mok_state"), we should not see any mok config
- * variables with data_size == 0.
- */
- assert_nonzero_goto(mok_entry->data_size, err, "%ld != 0\n");
+ mock_set_default_usage_limits();
- assert_equal_goto(mok_entry->data_size, mock_entry->data_size,
- err, "%ld != %ld\n");
- assert_zero_goto(CompareMem(mok_entry->data, mock_entry->data,
- mok_entry->data_size),
- err, "%ld != %ld\n");
- pos += offsetof(struct mok_variable_config_entry, data)
- + mok_entry->data_size;
- i += 1;
- }
-
- ret = 0;
-err:
- for (UINTN k = 0; k < n_mok_state_variables; k++) {
- struct mok_state_variable *v =
- &mok_state_variables[k];
- if (v->data_size && v->data) {
- free(v->data);
- v->data = NULL;
- v->data_size = 0;
- }
- }
-
- test_vars = NULL;
mock_set_variable_post_hook = NULL;
mock_get_variable_post_hook = NULL;
return ret;
@@ -391,7 +703,10 @@ main(void)
del_policy_names[j]);
mock_variable_delete_attr_policy = delete_policies[j];
- test(test_mok_mirror_0);
+ test(test_mok_mirror_with_enough_space);
+ mock_finalize_vars_and_configs();
+
+ test(test_mok_mirror_setvar_out_of_resources);
mock_finalize_vars_and_configs();
if (delete_policies[j] == 0)