[U-Boot] [PATCH 1/1] efi_selftest: do not write to linker generated array
Heinrich Schuchardt
xypron.glpk at gmx.de
Mon Oct 22 21:14:44 UTC 2018
On 10/22/2018 07:49 PM, Simon Glass wrote:
> Hi Heinrich,
>
> On 18 October 2018 at 23:51, Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
>> 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 at chromium.org>
>> Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
>> ---
>> include/efi_selftest.h | 2 --
>> lib/efi_selftest/efi_selftest.c | 31 ++++++++++++++++++++++---------
>> 2 files changed, 22 insertions(+), 11 deletions(-)
>
> Reviewed-by: Simon Glass <sjg at chromium.org>
>
> Thanks for doing this!
>
>>
>> diff --git a/include/efi_selftest.h b/include/efi_selftest.h
>> index 56beac305e..49d3d6d0b4 100644
>> --- a/include/efi_selftest.h
>> +++ b/include/efi_selftest.h
>> @@ -129,7 +129,6 @@ u16 efi_st_get_key(void);
>> * @setup: set up the unit test
>> * @teardown: tear down the unit test
>> * @execute: execute the unit test
>> - * @setup_ok: setup was successful (set at runtime)
>
> I'm not keen on the name setup_ok, which suggests a bool which would
> be true if it is OK.
>
> How about setup_err or setup_ret?
>
>> * @on_request: test is only executed on request
>> */
>> struct efi_unit_test {
>> @@ -139,7 +138,6 @@ struct efi_unit_test {
>> const struct efi_system_table *systable);
>> int (*execute)(void);
>> int (*teardown)(void);
>> - int setup_ok;
>> bool on_request;
>> };
>>
>> diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c
>> index dd338db687..fc7866365d 100644
>> --- a/lib/efi_selftest/efi_selftest.c
>> +++ b/lib/efi_selftest/efi_selftest.c
>> @@ -18,6 +18,7 @@ static const struct efi_boot_services *boottime;
>> static const struct efi_runtime_services *runtime;
>> static efi_handle_t handle;
>> static u16 reset_message[] = L"Selftest completed";
>> +static int *setup_ok;
>>
>> /*
>> * 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)
>> {
>> - if (!test->setup) {
>> - test->setup_ok = EFI_ST_SUCCESS;
>> + int ret;
>> +
>> + if (!test->setup)
>> return EFI_ST_SUCCESS;
>> - }
>> efi_st_printc(EFI_LIGHTBLUE, "\nSetting up '%s'\n", test->name);
>> - test->setup_ok = test->setup(handle, systable);
>> - if (test->setup_ok != EFI_ST_SUCCESS) {
>> + ret = test->setup(handle, systable);
>> + if (ret != EFI_ST_SUCCESS) {
>> efi_st_error("Setting up '%s' failed\n", test->name);
>> ++*failures;
>> } else {
>> efi_st_printc(EFI_LIGHTGREEN,
>> "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,
>> unsigned int steps, unsigned int *failures)
>> {
>> + int i = 0;
>> struct efi_unit_test *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 ?
>> efi_st_strcmp_16_8(testname, test->name) : test->on_request)
>> continue;
>> if (test->phase != phase)
>> continue;
>> if (steps & EFI_ST_SETUP)
>> - setup(test, failures);
>> - if (steps & EFI_ST_EXECUTE && test->setup_ok == EFI_ST_SUCCESS)
>> + setup_ok[i] = setup(test, failures);
>> + if (steps & EFI_ST_EXECUTE && setup_ok[i] == EFI_ST_SUCCESS)
>> execute(test, failures);
>> if (steps & EFI_ST_TEARDOWN)
>> 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,
>> 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);
>
> Isn't this calling the code you are trying to test and messing with
> the memory allocation tables? I wonder if you should allocate this in
> the caller or as part of the setup.
>
> Hmmm but I suppose you don't want to, since this is sort-of an EFI app?
I would prefer to keep efi_selftest self-sufficient so that one day we
can compile it as an app like we do with helloworld.efi.
Best regards
Heinrich
>
>> + if (ret != EFI_SUCCESS) {
>> + efi_st_error("Allocate pool failed\n");
>> + return ret;
>> + }
>> +
>> /* Execute boottime tests */
>> efi_st_do_tests(testname, EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
>> EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
>> --
>> 2.19.1
>>
>
> Regards,
> Simon
>
More information about the U-Boot
mailing list