]> git.proxmox.com Git - efi-boot-shim.git/blame - test-mok-mirror.c
Fix format strings for 32-bit builds
[efi-boot-shim.git] / test-mok-mirror.c
CommitLineData
8529e0f7
SM
1// SPDX-License-Identifier: BSD-2-Clause-Patent
2/*
3 * test-mok-mirror.c - try to test our mok mirroring code
4 * Copyright Peter Jones <pjones@redhat.com>
5 */
6
7#include "shim.h"
8#include "mock-variables.h"
9#include "test-data-efivars-1.h"
10
11#include <stdio.h>
12
13#pragma GCC diagnostic ignored "-Wunused-parameter"
14
15EFI_STATUS
16start_image(EFI_HANDLE image_handle UNUSED, CHAR16 *mm)
17{
18 printf("Attempted to launch %s\n", Str2str(mm));
19 return EFI_SUCCESS;
20}
21
22#define N_TEST_VAR_OPS 40
23struct test_var {
24 EFI_GUID guid;
25 CHAR16 *name;
26 UINT32 attrs;
27 UINTN n_ops;
28 bool must_be_present;
29 bool must_be_absent;
30 mock_variable_op_t ops[N_TEST_VAR_OPS];
31 EFI_STATUS results[N_TEST_VAR_OPS];
32};
33
34static struct test_var *test_vars;
35
36struct mock_mok_variable_config_entry {
37 CHAR8 name[256];
38 UINT64 data_size;
39 const unsigned char *data;
40};
41
42static void
43setvar_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)
47{
48 if (!test_vars)
49 return;
50
51 for (UINTN i = 0; test_vars[i].name != NULL; i++) {
52 struct test_var *tv = &test_vars[i];
53
54 if (CompareGuid(&tv->guid, guid) != 0 ||
55 StrCmp(tv->name, name) != 0)
56 continue;
57 tv->ops[tv->n_ops] = op;
58 tv->results[tv->n_ops] = *status;
59 tv->n_ops += 1;
60 }
61}
62
63static void
64getvar_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)
68{
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 ",
73 file, line, func,
74 GUID_ARGS(*guid), Str2str(name));
75 if (attrs)
76 printf("attrs:%s\n", format_var_attrs(*attrs));
77 else
78 printf("attrs:NULL\n");
79 printf("failed:%s\n", efi_strerror(*status));
80 }
81
82 if (!test_vars)
83 return;
84
85 for (UINTN i = 0; test_vars[i].name != NULL; i++) {
86 struct test_var *tv = &test_vars[i];
87
88 if (CompareGuid(&tv->guid, guid) != 0 ||
89 StrCmp(tv->name, name) != 0)
90 continue;
91 tv->ops[tv->n_ops] = GET;
92 tv->results[tv->n_ops] = *status;
93 tv->n_ops += 1;
94 }
95}
96
97static int
98test_mok_mirror_0(void)
99{
100 const char *mok_rt_vars[n_mok_state_variables];
101 EFI_STATUS status;
102 EFI_GUID guid = SHIM_LOCK_GUID;
103 EFI_GUID mok_config_guid = MOK_VARIABLE_STORE;
104 int ret = -1;
105
106 struct test_var test_mok_mirror_0_vars[] = {
107 {.guid = SHIM_LOCK_GUID,
108 .name = L"MokList",
109 .must_be_present = true,
110 .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
111 EFI_VARIABLE_NON_VOLATILE,
112 .ops = { NONE, },
113 },
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,
119 .ops = { NONE, },
120 },
121 {.guid = SHIM_LOCK_GUID,
122 .name = L"MokListX",
123 .must_be_present = true,
124 .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
125 EFI_VARIABLE_NON_VOLATILE,
126 .ops = { NONE, },
127 },
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,
133 .ops = { NONE, },
134 },
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,
140 .ops = { NONE, },
141 },
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,
147 .ops = { NONE, },
148 },
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,
154 .ops = { NONE, },
155 },
156 {.guid = SHIM_LOCK_GUID,
157 .name = L"MokSBState",
158 .attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
159 EFI_VARIABLE_NON_VOLATILE,
160 .ops = { NONE, },
161 },
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,
167 .ops = { NONE, },
168 },
169 {.guid = { 0, },
170 .name = NULL,
171 }
172 };
173
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
178 },
179 {.name = "MokListXRT",
180 .data_size = sizeof(test_data_efivars_1_MokListXRT),
181 .data = test_data_efivars_1_MokListXRT
182 },
183 {.name = "SbatLevelRT",
184 .data_size = sizeof(test_data_efivars_1_SbatLevelRT),
185 .data = test_data_efivars_1_SbatLevelRT
186 },
187 {.name = { 0, },
188 .data_size = 0,
189 .data = NULL,
190 }
191 };
192
193 for (size_t i = 0; i < n_mok_state_variables; i++) {
194 mok_rt_vars[i] = mok_state_variables[i].rtname8;
195 }
196
197 mock_load_variables("test-data/efivars-1", mok_rt_vars, true);
198
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];
202
203 import_mok_state(NULL);
204
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];
207 list_t *pos = NULL;
208 bool found = false;
209 char buf[1];
210 UINTN size = 0;
211 UINT32 attrs = 0;
212 bool present = false;
213
214 list_for_each(pos, &mock_variables) {
215 struct mock_variable *var;
216 bool deleted;
217 bool created;
218 int gets = 0;
219
220 var = list_entry(pos, struct mock_variable, list);
221 if (CompareGuid(&tv->guid, &var->guid) != 0 ||
222 StrCmp(var->name, tv->name) != 0)
223 continue;
224 found = true;
225 assert_equal_goto(var->attrs, tv->attrs, err,
226 "\"%s\": wrong attrs; got %s expected %s\n",
227 Str2str(tv->name),
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]) {
233 case NONE:
234 default:
235 break;
236 case CREATE:
237 if (tv->results[j] == EFI_SUCCESS)
238 created = true;
239 break;
240 case DELETE:
241 assert_goto(tv->results[j] != EFI_SUCCESS, err,
242 "Tried to delete absent variable \"%s\"\n",
243 Str2str(tv->name));
244 assert_goto(created == false, err,
245 "Deleted variable \"%s\" was previously created.\n",
246 Str2str(tv->name));
247 break;
248 case APPEND:
249 assert_goto(false, err,
250 "No append action should have been tested\n");
251 break;
252 case REPLACE:
253 assert_goto(false, err,
254 "No replace action should have been tested\n");
255 break;
256 case GET:
257 if (tv->results[j] == EFI_SUCCESS)
258 gets += 1;
259 break;
260 }
261 }
262 assert_goto(gets == 0 || gets == 1, err,
263 "Variable should not be read %d times.\n", gets);
264 }
265 if (tv->must_be_present) {
266 assert_goto(found == true, err,
267 "variable \"%s\" was not found.\n",
268 Str2str(tv->name));
269 }
270
271 if (tv->must_be_absent) {
272 assert_goto(found == false, err,
273 "variable \"%s\" was found.\n",
274 Str2str(tv->name));
275 }
276 }
277
278 uint8_t *pos = NULL;
279 for (size_t i = 0; i < ST->NumberOfTableEntries; i++) {
280 EFI_CONFIGURATION_TABLE *ct = &ST->ConfigurationTable[i];
281
282 if (CompareGuid(&ct->VendorGuid, &mok_config_guid) != 0)
283 continue;
284
285 pos = (void *)ct->VendorTable;
286 break;
287 }
288
289 assert_nonzero_goto(pos, err, "%p != 0\n");
290
291 size_t i = 0;
292 while (pos) {
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;
297
298 /*
299 * If the tables are different lengths, this will trigger.
300 */
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)
304 break;
305
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);
311
312 /*
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.
316 */
317 assert_nonzero_goto(mok_entry->data_size, err, "%ld != 0\n");
318
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;
326 i += 1;
327 }
328
329 ret = 0;
330err:
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) {
335 free(v->data);
336 v->data = NULL;
337 v->data_size = 0;
338 }
339 }
340
341 test_vars = NULL;
342 mock_set_variable_post_hook = NULL;
343 mock_get_variable_post_hook = NULL;
344 return ret;
345}
346
347int
348main(void)
349{
350 int status = 0;
351 setbuf(stdout, NULL);
352
353 const char *sort_policy_names[] = {
354 "MOCK_SORT_DESCENDING",
355 "MOCK_SORT_PREPEND",
356 "MOCK_SORT_APPEND",
357 "MOCK_SORT_ASCENDING",
358 "MOCK_SORT_MAX_SENTINEL"
359 };
360
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",
366 NULL
367 };
368
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,
374 0
375 };
376
377 for (int i = 0; i < MOCK_SORT_MAX_SENTINEL; i++) {
378 mock_variable_sort_policy = i;
379 mock_config_table_sort_policy = i;
380 int j = 0;
381
382 printf("%s: setting variable sort policy to %s\n",
383 program_invocation_short_name, sort_policy_names[i]);
384 do {
385 printf("%s: setting delete policy to %s\n",
386 program_invocation_short_name,
387 del_policy_names[j]);
388
389 mock_variable_delete_attr_policy = delete_policies[j];
390 test(test_mok_mirror_0);
391 mock_finalize_vars_and_configs();
392
393 if (delete_policies[j] == 0)
394 break;
395 } while (++j);
396 }
397
398 return status;
399}
400
401// vim:fenc=utf-8:tw=75:noet