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:

committed by
Alexander Graf

parent
81ea00838c
commit
4c174394ca
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
|
Reference in New Issue
Block a user