Skip to content

Commit 35dc110

Browse files
committed
mok: Fix memory leak in mok mirroring
Currently valgrind shows a minor issue which is not introduced in this patch series: ==2595397== ==2595397== HEAP SUMMARY: ==2595397== in use at exit: 16,368 bytes in 48 blocks ==2595397== total heap usage: 6,953 allocs, 6,905 frees, 9,146,749 bytes allocated ==2595397== ==2595397== 16,368 bytes in 48 blocks are definitely lost in loss record 1 of 1 ==2595397== at 0x4845464: calloc (vg_replace_malloc.c:1117) ==2595397== by 0x4087F2: mock_efi_allocate_pool (test.c:72) ==2595397== by 0x4098DE: UnknownInlinedFun (misc.c:33) ==2595397== by 0x4098DE: AllocateZeroPool (misc.c:48) ==2595397== by 0x403D40: get_variable_attr (variables.c:301) ==2595397== by 0x4071C4: import_one_mok_state (mok.c:831) ==2595397== by 0x4072F4: import_mok_state (mok.c:908) ==2595397== by 0x407FA6: test_mok_mirror_0 (test-mok-mirror.c:205) ==2595397== by 0x4035B2: main (test-mok-mirror.c:378) ==2595397== ==2595397== LEAK SUMMARY: ==2595397== definitely lost: 16,368 bytes in 48 blocks ==2595397== indirectly lost: 0 bytes in 0 blocks ==2595397== possibly lost: 0 bytes in 0 blocks ==2595397== still reachable: 0 bytes in 0 blocks ==2595397== suppressed: 0 bytes in 0 blocks ==2595397== This is because we're doing get_variable_attr() on the same variable more than once and saving the value to our variables table. Each additional time we do so leaks the previous one. This patch solves the issue by not getting the variable again if it's already set in the table, and adds a test case to check if we're doing get_variable() of any variety on the same variable more than once. Signed-off-by: Peter Jones <pjones@redhat.com>
1 parent 397f820 commit 35dc110

File tree

3 files changed

+48
-23
lines changed

3 files changed

+48
-23
lines changed

include/mock-variables.h

+2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ typedef enum {
122122
DELETE,
123123
APPEND,
124124
REPLACE,
125+
GET,
125126
} mock_variable_op_t;
126127

127128
static inline const char *
@@ -133,6 +134,7 @@ format_var_op(mock_variable_op_t op)
133134
"DELETE",
134135
"APPEND",
135136
"REPLACE",
137+
"GET",
136138
NULL
137139
};
138140

mok.c

+25-23
Original file line numberDiff line numberDiff line change
@@ -828,30 +828,32 @@ EFI_STATUS import_one_mok_state(struct mok_state_variable *v,
828828

829829
dprint(L"importing mok state for \"%s\"\n", v->name);
830830

831-
efi_status = get_variable_attr(v->name,
832-
&v->data, &v->data_size,
833-
*v->guid, &attrs);
834-
if (efi_status == EFI_NOT_FOUND) {
835-
v->data = NULL;
836-
v->data_size = 0;
837-
} else if (EFI_ERROR(efi_status)) {
838-
perror(L"Could not verify %s: %r\n", v->name,
839-
efi_status);
840-
delete = TRUE;
841-
} else {
842-
if (!(attrs & v->yes_attr)) {
843-
perror(L"Variable %s is missing attributes:\n",
844-
v->name);
845-
perror(L" 0x%08x should have 0x%08x set.\n",
846-
attrs, v->yes_attr);
847-
delete = TRUE;
848-
}
849-
if (attrs & v->no_attr) {
850-
perror(L"Variable %s has incorrect attribute:\n",
851-
v->name);
852-
perror(L" 0x%08x should not have 0x%08x set.\n",
853-
attrs, v->no_attr);
831+
if (!v->data && !v->data_size) {
832+
efi_status = get_variable_attr(v->name,
833+
&v->data, &v->data_size,
834+
*v->guid, &attrs);
835+
if (efi_status == EFI_NOT_FOUND) {
836+
v->data = NULL;
837+
v->data_size = 0;
838+
} else if (EFI_ERROR(efi_status)) {
839+
perror(L"Could not verify %s: %r\n", v->name,
840+
efi_status);
854841
delete = TRUE;
842+
} else {
843+
if (!(attrs & v->yes_attr)) {
844+
perror(L"Variable %s is missing attributes:\n",
845+
v->name);
846+
perror(L" 0x%08x should have 0x%08x set.\n",
847+
attrs, v->yes_attr);
848+
delete = TRUE;
849+
}
850+
if (attrs & v->no_attr) {
851+
perror(L"Variable %s has incorrect attribute:\n",
852+
v->name);
853+
perror(L" 0x%08x should not have 0x%08x set.\n",
854+
attrs, v->no_attr);
855+
delete = TRUE;
856+
}
855857
}
856858
}
857859
if (delete == TRUE) {

test-mok-mirror.c

+21
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ getvar_post(CHAR16 *name, EFI_GUID *guid,
7878
printf("attrs:NULL\n");
7979
printf("failed:%s\n", efi_strerror(*status));
8080
}
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+
}
8195
}
8296

8397
static int
@@ -201,6 +215,7 @@ test_mok_mirror_0(void)
201215
struct mock_variable *var;
202216
bool deleted;
203217
bool created;
218+
int gets = 0;
204219

205220
var = list_entry(pos, struct mock_variable, list);
206221
if (CompareGuid(&tv->guid, &var->guid) != 0 ||
@@ -238,8 +253,14 @@ test_mok_mirror_0(void)
238253
assert_goto(false, err,
239254
"No replace action should have been tested\n");
240255
break;
256+
case GET:
257+
if (tv->results[j] == EFI_SUCCESS)
258+
gets += 1;
259+
break;
241260
}
242261
}
262+
assert_goto(gets == 0 || gets == 1, err,
263+
"Variable should not be read %d times.\n", gets);
243264
}
244265
if (tv->must_be_present) {
245266
assert_goto(found == true, err,

0 commit comments

Comments
 (0)