Skip to content

Commit

Permalink
tests: Add a unit test for mok mirroring.
Browse files Browse the repository at this point in the history
  • Loading branch information
vathpela committed Aug 3, 2021
1 parent 80ef7fd commit ca116c7
Showing 1 changed file with 268 additions and 0 deletions.
268 changes: 268 additions & 0 deletions test-mok-mirror.c
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

0 comments on commit ca116c7

Please sign in to comment.