diff options
| author | Christian Breunig <christian@breunig.cc> | 2025-07-06 21:59:18 +0200 |
|---|---|---|
| committer | Christian Breunig <christian@breunig.cc> | 2025-07-06 21:59:18 +0200 |
| commit | 02acad285c74015e8120ade2b41d51b39ae66b63 (patch) | |
| tree | 980533ac963ac23bc9e090e3e4212bdb9e225a05 /test-mok-mirror.c | |
| parent | 1c1d50da810e6c49e804a74719c2675b88b033a6 (diff) | |
| parent | 18d98bfb34be583a5fe2987542e4b15e0db9cb61 (diff) | |
| download | efi-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.c | 575 |
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) |
