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>
diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c
index dd338db..fc78663 100644
--- a/lib/efi_selftest/efi_selftest.c
+++ b/lib/efi_selftest/efi_selftest.c
@@ -18,6 +18,7 @@
 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 @@
  */
 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 @@
 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 @@
 			      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);
+	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,