Skip to content

Commit c5d91b1

Browse files
cyrillosardbiesheuvel
authored andcommitted
efi: Fix memory leak in efivar_ssdt_load
When we load SSDT from efi variable (specified with efivar_ssdt=<var> boot command line argument) a name for the variable is allocated dynamically because we traverse all EFI variables. Unlike ACPI table data, which is later used by ACPI engine, the name is no longer needed once traverse is complete -- don't forget to free this memory. Same time we silently ignore any errors happened here let's print a message if something went wrong (but do not exit since this is not a critical error and the system should continue to boot). Also while here -- add a note why we keep SSDT table on success. Signed-off-by: Cyrill Gorcunov <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent 8510622 commit c5d91b1

File tree

1 file changed

+28
-13
lines changed
  • drivers/firmware/efi

1 file changed

+28
-13
lines changed

drivers/firmware/efi/efi.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ static __init int efivar_ssdt_load(void)
273273
efi_char16_t *name = NULL;
274274
efi_status_t status;
275275
efi_guid_t guid;
276+
int ret = 0;
276277

277278
if (!efivar_ssdt[0])
278279
return 0;
@@ -294,8 +295,8 @@ static __init int efivar_ssdt_load(void)
294295
efi_char16_t *name_tmp =
295296
krealloc(name, name_size, GFP_KERNEL);
296297
if (!name_tmp) {
297-
kfree(name);
298-
return -ENOMEM;
298+
ret = -ENOMEM;
299+
goto out;
299300
}
300301
name = name_tmp;
301302
continue;
@@ -309,26 +310,38 @@ static __init int efivar_ssdt_load(void)
309310
pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt, &guid);
310311

311312
status = efi.get_variable(name, &guid, NULL, &data_size, NULL);
312-
if (status != EFI_BUFFER_TOO_SMALL || !data_size)
313-
return -EIO;
313+
if (status != EFI_BUFFER_TOO_SMALL || !data_size) {
314+
ret = -EIO;
315+
goto out;
316+
}
314317

315318
data = kmalloc(data_size, GFP_KERNEL);
316-
if (!data)
317-
return -ENOMEM;
319+
if (!data) {
320+
ret = -ENOMEM;
321+
goto out;
322+
}
318323

319324
status = efi.get_variable(name, &guid, NULL, &data_size, data);
320325
if (status == EFI_SUCCESS) {
321-
acpi_status ret = acpi_load_table(data, NULL);
322-
if (ret)
323-
pr_err("failed to load table: %u\n", ret);
324-
else
326+
acpi_status acpi_ret = acpi_load_table(data, NULL);
327+
if (ACPI_FAILURE(acpi_ret)) {
328+
pr_err("efivar_ssdt: failed to load table: %u\n",
329+
acpi_ret);
330+
} else {
331+
/*
332+
* The @data will be in use by ACPI engine,
333+
* do not free it!
334+
*/
325335
continue;
336+
}
326337
} else {
327-
pr_err("failed to get var data: 0x%lx\n", status);
338+
pr_err("efivar_ssdt: failed to get var data: 0x%lx\n", status);
328339
}
329340
kfree(data);
330341
}
331-
return 0;
342+
out:
343+
kfree(name);
344+
return ret;
332345
}
333346
#else
334347
static inline int efivar_ssdt_load(void) { return 0; }
@@ -433,7 +446,9 @@ static int __init efisubsys_init(void)
433446
error = generic_ops_register();
434447
if (error)
435448
goto err_put;
436-
efivar_ssdt_load();
449+
error = efivar_ssdt_load();
450+
if (error)
451+
pr_err("efi: failed to load SSDT, error %d.\n", error);
437452
platform_device_register_simple("efivars", 0, NULL, 0);
438453
}
439454

0 commit comments

Comments
 (0)