efi_selftest: do not write to linker generated array

Linker generated arrays may be stored in code sections of memory that are
not writable. So let's allocate setup_ok as an array at runtime.

This avoids an illegal memory access observed in the sandbox.

Reported-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Heinrich Schuchardt
2018-10-19 07:51:26 +02:00
committed by Alexander Graf
parent 81ea00838c
commit 4c174394ca
2 changed files with 22 additions and 11 deletions

View File

@@ -129,7 +129,6 @@ u16 efi_st_get_key(void);
* @setup: set up the unit test * @setup: set up the unit test
* @teardown: tear down the unit test * @teardown: tear down the unit test
* @execute: execute the unit test * @execute: execute the unit test
* @setup_ok: setup was successful (set at runtime)
* @on_request: test is only executed on request * @on_request: test is only executed on request
*/ */
struct efi_unit_test { struct efi_unit_test {
@@ -139,7 +138,6 @@ struct efi_unit_test {
const struct efi_system_table *systable); const struct efi_system_table *systable);
int (*execute)(void); int (*execute)(void);
int (*teardown)(void); int (*teardown)(void);
int setup_ok;
bool on_request; bool on_request;
}; };

View File

@@ -18,6 +18,7 @@ static const struct efi_boot_services *boottime;
static const struct efi_runtime_services *runtime; static const struct efi_runtime_services *runtime;
static efi_handle_t handle; static efi_handle_t handle;
static u16 reset_message[] = L"Selftest completed"; static u16 reset_message[] = L"Selftest completed";
static int *setup_ok;
/* /*
* Exit the boot services. * Exit the boot services.
@@ -74,20 +75,20 @@ void efi_st_exit_boot_services(void)
*/ */
static int setup(struct efi_unit_test *test, unsigned int *failures) static int setup(struct efi_unit_test *test, unsigned int *failures)
{ {
if (!test->setup) { int ret;
test->setup_ok = EFI_ST_SUCCESS;
if (!test->setup)
return EFI_ST_SUCCESS; return EFI_ST_SUCCESS;
}
efi_st_printc(EFI_LIGHTBLUE, "\nSetting up '%s'\n", test->name); efi_st_printc(EFI_LIGHTBLUE, "\nSetting up '%s'\n", test->name);
test->setup_ok = test->setup(handle, systable); ret = test->setup(handle, systable);
if (test->setup_ok != EFI_ST_SUCCESS) { if (ret != EFI_ST_SUCCESS) {
efi_st_error("Setting up '%s' failed\n", test->name); efi_st_error("Setting up '%s' failed\n", test->name);
++*failures; ++*failures;
} else { } else {
efi_st_printc(EFI_LIGHTGREEN, efi_st_printc(EFI_LIGHTGREEN,
"Setting up '%s' succeeded\n", test->name); "Setting up '%s' succeeded\n", test->name);
} }
return test->setup_ok; return ret;
} }
/* /*
@@ -186,18 +187,20 @@ static void list_all_tests(void)
void efi_st_do_tests(const u16 *testname, unsigned int phase, void efi_st_do_tests(const u16 *testname, unsigned int phase,
unsigned int steps, unsigned int *failures) unsigned int steps, unsigned int *failures)
{ {
int i = 0;
struct efi_unit_test *test; struct efi_unit_test *test;
for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { test < ll_entry_end(struct efi_unit_test, efi_unit_test);
++test, ++i) {
if (testname ? if (testname ?
efi_st_strcmp_16_8(testname, test->name) : test->on_request) efi_st_strcmp_16_8(testname, test->name) : test->on_request)
continue; continue;
if (test->phase != phase) if (test->phase != phase)
continue; continue;
if (steps & EFI_ST_SETUP) if (steps & EFI_ST_SETUP)
setup(test, failures); setup_ok[i] = setup(test, failures);
if (steps & EFI_ST_EXECUTE && test->setup_ok == EFI_ST_SUCCESS) if (steps & EFI_ST_EXECUTE && setup_ok[i] == EFI_ST_SUCCESS)
execute(test, failures); execute(test, failures);
if (steps & EFI_ST_TEARDOWN) if (steps & EFI_ST_TEARDOWN)
teardown(test, failures); teardown(test, failures);
@@ -271,6 +274,16 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
ll_entry_count(struct efi_unit_test, ll_entry_count(struct efi_unit_test,
efi_unit_test)); efi_unit_test));
/* Allocate buffer for setup results */
ret = boottime->allocate_pool(EFI_RUNTIME_SERVICES_DATA, sizeof(int) *
ll_entry_count(struct efi_unit_test,
efi_unit_test),
(void **)&setup_ok);
if (ret != EFI_SUCCESS) {
efi_st_error("Allocate pool failed\n");
return ret;
}
/* Execute boottime tests */ /* Execute boottime tests */
efi_st_do_tests(testname, EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, efi_st_do_tests(testname, EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN, EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,