1 // SPDX-License-Identifier: BSD-2-Clause-Patent
3 * test-mok-mirror.c - try to test our mok mirroring code
4 * Copyright Peter Jones <pjones@redhat.com>
8 #include "mock-variables.h"
9 #include "test-data-efivars-1.h"
13 #pragma GCC diagnostic ignored "-Wunused-parameter"
16 start_image(EFI_HANDLE image_handle UNUSED
, CHAR16
*mm
)
18 printf("Attempted to launch %s\n", Str2str(mm
));
22 #define N_TEST_VAR_OPS 40
30 mock_variable_op_t ops
[N_TEST_VAR_OPS
];
31 EFI_STATUS results
[N_TEST_VAR_OPS
];
34 static struct test_var
*test_vars
;
36 struct mock_mok_variable_config_entry
{
39 const unsigned char *data
;
43 setvar_post(CHAR16
*name
, EFI_GUID
*guid
, UINT32 attrs
,
44 UINTN size
, VOID
*data
, EFI_STATUS
*status
,
45 mock_variable_op_t op
, const char * const file
,
46 const int line
, const char * const func
)
51 for (UINTN i
= 0; test_vars
[i
].name
!= NULL
; i
++) {
52 struct test_var
*tv
= &test_vars
[i
];
54 if (CompareGuid(&tv
->guid
, guid
) != 0 ||
55 StrCmp(tv
->name
, name
) != 0)
57 tv
->ops
[tv
->n_ops
] = op
;
58 tv
->results
[tv
->n_ops
] = *status
;
64 getvar_post(CHAR16
*name
, EFI_GUID
*guid
,
65 UINT32
*attrs
, UINTN
*size
,
66 VOID
*data
, EFI_STATUS
*status
,
67 const char * const file
, const int line
, const char * func
)
69 if (EFI_ERROR(*status
) &&
70 (*status
!= EFI_NOT_FOUND
&&
71 *status
!= EFI_BUFFER_TOO_SMALL
)) {
72 printf("%s:%d:%s():Getting "GUID_FMT
"-%s ",
74 GUID_ARGS(*guid
), Str2str(name
));
76 printf("attrs:%s\n", format_var_attrs(*attrs
));
78 printf("attrs:NULL\n");
79 printf("failed:%s\n", efi_strerror(*status
));
85 for (UINTN i
= 0; test_vars
[i
].name
!= NULL
; i
++) {
86 struct test_var
*tv
= &test_vars
[i
];
88 if (CompareGuid(&tv
->guid
, guid
) != 0 ||
89 StrCmp(tv
->name
, name
) != 0)
91 tv
->ops
[tv
->n_ops
] = GET
;
92 tv
->results
[tv
->n_ops
] = *status
;
98 test_mok_mirror_0(void)
100 const char *mok_rt_vars
[n_mok_state_variables
];
102 EFI_GUID guid
= SHIM_LOCK_GUID
;
103 EFI_GUID mok_config_guid
= MOK_VARIABLE_STORE
;
106 struct test_var test_mok_mirror_0_vars
[] = {
107 {.guid
= SHIM_LOCK_GUID
,
109 .must_be_present
= true,
110 .attrs
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|
111 EFI_VARIABLE_NON_VOLATILE
,
114 {.guid
= SHIM_LOCK_GUID
,
115 .name
= L
"MokListRT",
116 .must_be_present
= true,
117 .attrs
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|
118 EFI_VARIABLE_RUNTIME_ACCESS
,
121 {.guid
= SHIM_LOCK_GUID
,
123 .must_be_present
= true,
124 .attrs
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|
125 EFI_VARIABLE_NON_VOLATILE
,
128 {.guid
= SHIM_LOCK_GUID
,
129 .name
= L
"MokListXRT",
130 .must_be_present
= true,
131 .attrs
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|
132 EFI_VARIABLE_RUNTIME_ACCESS
,
135 {.guid
= SHIM_LOCK_GUID
,
136 .name
= L
"SbatLevel",
137 .must_be_present
= true,
138 .attrs
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|
139 EFI_VARIABLE_NON_VOLATILE
,
142 {.guid
= SHIM_LOCK_GUID
,
143 .name
= L
"SbatLevelRT",
144 .must_be_present
= true,
145 .attrs
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|
146 EFI_VARIABLE_RUNTIME_ACCESS
,
149 {.guid
= SHIM_LOCK_GUID
,
150 .name
= L
"MokIgnoreDB",
151 .must_be_absent
= true,
152 .attrs
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|
153 EFI_VARIABLE_RUNTIME_ACCESS
,
156 {.guid
= SHIM_LOCK_GUID
,
157 .name
= L
"MokSBState",
158 .attrs
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|
159 EFI_VARIABLE_NON_VOLATILE
,
162 {.guid
= SHIM_LOCK_GUID
,
163 .name
= L
"MokSBStateRT",
164 .must_be_absent
= true,
165 .attrs
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|
166 EFI_VARIABLE_RUNTIME_ACCESS
,
174 struct mock_mok_variable_config_entry test_mok_config_table
[] = {
175 {.name
= "MokListRT",
176 .data_size
= sizeof(test_data_efivars_1_MokListRT
),
177 .data
= test_data_efivars_1_MokListRT
179 {.name
= "MokListXRT",
180 .data_size
= sizeof(test_data_efivars_1_MokListXRT
),
181 .data
= test_data_efivars_1_MokListXRT
183 {.name
= "SbatLevelRT",
184 .data_size
= sizeof(test_data_efivars_1_SbatLevelRT
),
185 .data
= test_data_efivars_1_SbatLevelRT
193 for (size_t i
= 0; i
< n_mok_state_variables
; i
++) {
194 mok_rt_vars
[i
] = mok_state_variables
[i
].rtname8
;
197 mock_load_variables("test-data/efivars-1", mok_rt_vars
, true);
199 mock_set_variable_post_hook
= setvar_post
;
200 mock_get_variable_post_hook
= getvar_post
;
201 test_vars
= &test_mok_mirror_0_vars
[0];
203 import_mok_state(NULL
);
205 for (size_t i
= 0; test_mok_mirror_0_vars
[i
].name
!= NULL
; i
++) {
206 struct test_var
*tv
= &test_mok_mirror_0_vars
[i
];
212 bool present
= false;
214 list_for_each(pos
, &mock_variables
) {
215 struct mock_variable
*var
;
220 var
= list_entry(pos
, struct mock_variable
, list
);
221 if (CompareGuid(&tv
->guid
, &var
->guid
) != 0 ||
222 StrCmp(var
->name
, tv
->name
) != 0)
225 assert_equal_goto(var
->attrs
, tv
->attrs
, err
,
226 "\"%s\": wrong attrs; got %s expected %s\n",
228 format_var_attrs(var
->attrs
),
229 format_var_attrs(tv
->attrs
));
230 for (UINTN j
= 0; j
< N_TEST_VAR_OPS
231 && tv
->ops
[j
] != NONE
; j
++) {
232 switch (tv
->ops
[j
]) {
237 if (tv
->results
[j
] == EFI_SUCCESS
)
241 assert_goto(tv
->results
[j
] != EFI_SUCCESS
, err
,
242 "Tried to delete absent variable \"%s\"\n",
244 assert_goto(created
== false, err
,
245 "Deleted variable \"%s\" was previously created.\n",
249 assert_goto(false, err
,
250 "No append action should have been tested\n");
253 assert_goto(false, err
,
254 "No replace action should have been tested\n");
257 if (tv
->results
[j
] == EFI_SUCCESS
)
262 assert_goto(gets
== 0 || gets
== 1, err
,
263 "Variable should not be read %d times.\n", gets
);
265 if (tv
->must_be_present
) {
266 assert_goto(found
== true, err
,
267 "variable \"%s\" was not found.\n",
271 if (tv
->must_be_absent
) {
272 assert_goto(found
== false, err
,
273 "variable \"%s\" was found.\n",
279 for (size_t i
= 0; i
< ST
->NumberOfTableEntries
; i
++) {
280 EFI_CONFIGURATION_TABLE
*ct
= &ST
->ConfigurationTable
[i
];
282 if (CompareGuid(&ct
->VendorGuid
, &mok_config_guid
) != 0)
285 pos
= (void *)ct
->VendorTable
;
289 assert_nonzero_goto(pos
, err
, "%p != 0\n");
293 struct mock_mok_variable_config_entry
*mock_entry
=
294 &test_mok_config_table
[i
];
295 struct mok_variable_config_entry
*mok_entry
=
296 (struct mok_variable_config_entry
*)pos
;
299 * If the tables are different lengths, this will trigger.
301 assert_equal_goto(mok_entry
->name
[0], mock_entry
->name
[0], err
,
302 "mok.name[0] %ld != test.name[0] %ld\n");
303 if (mock_entry
->name
[0] == 0)
306 assert_nonzero_goto(mok_entry
->name
[0], err
, "%ld != %ld\n");
307 assert_zero_goto(strncmp(mok_entry
->name
, mock_entry
->name
,
308 sizeof(mock_entry
->name
)),
309 err
, "%ld != %ld: strcmp(\"%s\",\"%s\")\n",
310 mok_entry
->name
, mock_entry
->name
);
313 * As of 7501b6bb449f ("mok: fix potential buffer overrun in
314 * import_mok_state"), we should not see any mok config
315 * variables with data_size == 0.
317 assert_nonzero_goto(mok_entry
->data_size
, err
, "%ld != 0\n");
319 assert_equal_goto(mok_entry
->data_size
, mock_entry
->data_size
,
320 err
, "%ld != %ld\n");
321 assert_zero_goto(CompareMem(mok_entry
->data
, mock_entry
->data
,
322 mok_entry
->data_size
),
323 err
, "%ld != %ld\n");
324 pos
+= offsetof(struct mok_variable_config_entry
, data
)
325 + mok_entry
->data_size
;
331 for (UINTN k
= 0; k
< n_mok_state_variables
; k
++) {
332 struct mok_state_variable
*v
=
333 &mok_state_variables
[k
];
334 if (v
->data_size
&& v
->data
) {
342 mock_set_variable_post_hook
= NULL
;
343 mock_get_variable_post_hook
= NULL
;
351 setbuf(stdout
, NULL
);
353 const char *sort_policy_names
[] = {
354 "MOCK_SORT_DESCENDING",
357 "MOCK_SORT_ASCENDING",
358 "MOCK_SORT_MAX_SENTINEL"
361 const char *del_policy_names
[] = {
362 "MOCK_VAR_DELETE_ATTR_ALLOW_ZERO",
363 "MOCK_VAR_DELETE_ATTR_ALOW_MISMATCH",
364 "MOCK_VAR_DELETE_ATTR_ALLOW_ZERO|MOCK_VAR_DELETE_ATTR_ALOW_MISMATCH",
365 "MOCK_VAR_DELETE_ATTR_ALLOW_NONE",
369 int delete_policies
[] = {
370 MOCK_VAR_DELETE_ATTR_ALLOW_ZERO
,
371 MOCK_VAR_DELETE_ATTR_ALOW_MISMATCH
,
372 MOCK_VAR_DELETE_ATTR_ALLOW_ZERO
373 | MOCK_VAR_DELETE_ATTR_ALOW_MISMATCH
,
377 for (int i
= 0; i
< MOCK_SORT_MAX_SENTINEL
; i
++) {
378 mock_variable_sort_policy
= i
;
379 mock_config_table_sort_policy
= i
;
382 printf("%s: setting variable sort policy to %s\n",
383 program_invocation_short_name
, sort_policy_names
[i
]);
385 printf("%s: setting delete policy to %s\n",
386 program_invocation_short_name
,
387 del_policy_names
[j
]);
389 mock_variable_delete_attr_policy
= delete_policies
[j
];
390 test(test_mok_mirror_0
);
391 mock_finalize_vars_and_configs();
393 if (delete_policies
[j
] == 0)
401 // vim:fenc=utf-8:tw=75:noet