-
Notifications
You must be signed in to change notification settings - Fork 291
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: Add a unit test for mok mirroring.
- Loading branch information
Showing
1 changed file
with
268 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,268 @@ | ||
// SPDX-License-Identifier: BSD-2-Clause-Patent | ||
/* | ||
* test-mok-mirror.c - try to test our mok mirroring code | ||
* Copyright Peter Jones <pjones@redhat.com> | ||
*/ | ||
|
||
#include "shim.h" | ||
|
||
#include <stdio.h> | ||
|
||
#pragma GCC diagnostic ignored "-Wunused-parameter" | ||
|
||
EFI_STATUS | ||
start_image(EFI_HANDLE image_handle UNUSED, CHAR16 *mm) | ||
{ | ||
printf("Attempted to launch %s\n", Str2str(mm)); | ||
return EFI_SUCCESS; | ||
} | ||
|
||
#define N_TEST_VAR_OPS 40 | ||
struct test_var { | ||
EFI_GUID guid; | ||
CHAR16 *name; | ||
UINT32 attrs; | ||
UINTN n_ops; | ||
mock_variable_op_t ops[N_TEST_VAR_OPS]; | ||
EFI_STATUS results[N_TEST_VAR_OPS]; | ||
}; | ||
|
||
static struct test_var *test_vars; | ||
|
||
static EFI_STATUS | ||
setvar_pre(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, VOID *data) | ||
{ | ||
#if 0 | ||
printf("%s:%d:%s(): SetVariable(\"%s\", "GUID_FMT", ", | ||
__FILE__, __LINE__-1, __func__, | ||
Str2str(name), GUID_ARGS(*guid)); | ||
printf("attrs:%s, size:%lu, data:%p)\n", attrs ? format_var_attrs(attrs) : "(nil)", | ||
size, data); | ||
#endif | ||
return EFI_SUCCESS; | ||
} | ||
|
||
static void | ||
setvar_post(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, | ||
UINTN size, VOID *data, EFI_STATUS *status, | ||
mock_variable_op_t op, const char * const file, | ||
const int line, const char * const func) | ||
{ | ||
list_t *pos = NULL; | ||
|
||
if (!test_vars) | ||
return; | ||
|
||
for (UINTN i = 0; test_vars[i].name != NULL; i++) { | ||
struct test_var *tv = &test_vars[i]; | ||
|
||
if (CompareGuid(&tv->guid, guid) != 0 || | ||
StrCmp(tv->name, name) != 0) | ||
continue; | ||
tv->ops[tv->n_ops] = op; | ||
tv->results[tv->n_ops] = *status; | ||
tv->n_ops += 1; | ||
} | ||
|
||
#if 0 | ||
char *ops[] = { | ||
"NoOp", | ||
"NewVariable", | ||
"DeleteVariable", | ||
"AppendVariable", | ||
"ReplaceVariable", | ||
}; | ||
printf("%s:%d:%s():%s(\"%s\", " | ||
GUID_FMT", attrs:%s, size:%lu, data:%p) = %s\n", | ||
file, line, func, ops[op], | ||
Str2str(name), GUID_ARGS(*guid), | ||
format_var_attrs(attrs), size, data, | ||
efi_strerror(*status)); | ||
#endif | ||
} | ||
|
||
static EFI_STATUS | ||
getvar_pre(CHAR16 *name, EFI_GUID *guid, UINT32 *attrs, UINTN *size, VOID *data) | ||
{ | ||
#if 0 | ||
printf("%s:%d:%s(): GetVariable(\"%s\", "GUID_FMT", %p, %p, %p)\n", | ||
__FILE__, __LINE__-1, __func__, | ||
Str2str(name), GUID_ARGS(*guid), attrs, size, data); | ||
#endif | ||
return EFI_SUCCESS; | ||
} | ||
|
||
static void | ||
getvar_post(CHAR16 *name, EFI_GUID *guid, | ||
UINT32 *attrs, UINTN *size, | ||
VOID *data, EFI_STATUS *status, | ||
const char * const file, const int line, const char * func) | ||
{ | ||
if (EFI_ERROR(*status) && | ||
(*status != EFI_NOT_FOUND && | ||
*status != EFI_BUFFER_TOO_SMALL)) { | ||
printf("%s:%d:%s():Getting "GUID_FMT"-%s ", | ||
file, line, func, | ||
GUID_ARGS(*guid), Str2str(name)); | ||
if (attrs) | ||
printf("attrs:%s\n", format_var_attrs(*attrs)); | ||
else | ||
printf("attrs:NULL\n"); | ||
printf("failed:%s\n", efi_strerror(*status)); | ||
} | ||
} | ||
|
||
static int | ||
test_mok_mirror_0(void) | ||
{ | ||
const char *mok_rt_vars[n_mok_state_variables]; | ||
EFI_STATUS status; | ||
EFI_GUID guid = SHIM_LOCK_GUID; | ||
int ret = -1; | ||
|
||
struct test_var test_mok_mirror_0_vars[] = { | ||
{.guid = SHIM_LOCK_GUID, | ||
.name = L"MokListRT", | ||
.attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS| | ||
EFI_VARIABLE_RUNTIME_ACCESS, | ||
.ops = { NONE, }, | ||
}, | ||
{.guid = { 0, }, | ||
.name = NULL, | ||
} | ||
}; | ||
|
||
for (size_t i = 0; i < n_mok_state_variables; i++) { | ||
mok_rt_vars[i] = mok_state_variables[i].rtname8; | ||
} | ||
|
||
mock_load_variables("test-data/efivars-1", mok_rt_vars, true); | ||
|
||
mock_set_variable_pre_hook = setvar_pre; | ||
mock_set_variable_post_hook = setvar_post; | ||
mock_get_variable_pre_hook = getvar_pre; | ||
mock_get_variable_post_hook = getvar_post; | ||
test_vars = &test_mok_mirror_0_vars[0]; | ||
|
||
import_mok_state(NULL); | ||
|
||
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; | ||
|
||
list_for_each(pos, &mock_variables) { | ||
struct mock_variable *var; | ||
bool deleted; | ||
bool created; | ||
|
||
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++) { | ||
if (tv->ops[j] == CREATE && | ||
tv->results[j] == EFI_SUCCESS) | ||
created = true; | ||
if (tv->ops[j] == DELETE && | ||
tv->results[j] == EFI_SUCCESS) { | ||
assert_false_goto(created, err, | ||
"created:%d deleted variable \"%s\" was previously created.\n", | ||
Str2str(tv->name)); | ||
} | ||
assert_true_goto( | ||
tv->results[j] == EFI_SUCCESS || | ||
tv->results[j] == EFI_NOT_FOUND || | ||
tv->results[j] == EFI_BAD_BUFFER_SIZE, | ||
err, | ||
":%d Bad error status for variable \"%s\"\n", | ||
Str2str(tv->name)); | ||
} | ||
} | ||
assert_true_goto(found, err, | ||
"found:%d variable \"%s\" was not found.\n", | ||
Str2str(tv->name)); | ||
} | ||
|
||
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_pre_hook = NULL; | ||
mock_set_variable_post_hook = NULL; | ||
mock_get_variable_pre_hook = NULL; | ||
mock_get_variable_post_hook = NULL; | ||
return ret; | ||
} | ||
|
||
int | ||
main(void) | ||
{ | ||
int status = 0; | ||
setbuf(stdout, NULL); | ||
|
||
const char *sort_policy_names[] = { | ||
"MOCK_SORT_DESCENDING", | ||
"MOCK_SORT_PREPEND", | ||
"MOCK_SORT_APPEND", | ||
"MOCK_SORT_ASCENDING", | ||
"MOCK_SORT_MAX_SENTINEL" | ||
}; | ||
|
||
const char *del_policy_names[] = { | ||
"MOCK_VAR_DELETE_ATTR_ALLOW_ZERO", | ||
"MOCK_VAR_DELETE_ATTR_ALOW_MISMATCH", | ||
"MOCK_VAR_DELETE_ATTR_ALLOW_ZERO|MOCK_VAR_DELETE_ATTR_ALOW_MISMATCH", | ||
"MOCK_VAR_DELETE_ATTR_ALLOW_NONE", | ||
NULL | ||
}; | ||
|
||
int delete_policies[] = { | ||
MOCK_VAR_DELETE_ATTR_ALLOW_ZERO, | ||
MOCK_VAR_DELETE_ATTR_ALOW_MISMATCH, | ||
MOCK_VAR_DELETE_ATTR_ALLOW_ZERO | ||
| MOCK_VAR_DELETE_ATTR_ALOW_MISMATCH, | ||
0 | ||
}; | ||
|
||
for (int i = 0; i < MOCK_SORT_MAX_SENTINEL; i++) { | ||
mock_variable_sort_policy = i; | ||
mock_config_table_sort_policy = i; | ||
int j = 0; | ||
|
||
printf("%s: setting variable sort policy to %s\n", | ||
program_invocation_short_name, sort_policy_names[i]); | ||
do { | ||
printf("%s: setting delete policy to %s\n", | ||
program_invocation_short_name, | ||
del_policy_names[j]); | ||
|
||
mock_variable_delete_attr_policy = delete_policies[j]; | ||
test(test_mok_mirror_0); | ||
mock_finalize_vars_and_configs(); | ||
|
||
if (delete_policies[j] == 0) | ||
break; | ||
} while (++j); | ||
} | ||
|
||
return status; | ||
} | ||
|
||
// vim:fenc=utf-8:tw=75:noet |