[v3,16/17] sandbox: Allow to execute from RAM

Message ID 20180615124229.35310-17-agraf@suse.de
State New
Headers show
Series
  • sandbox: efi_loader support
Related show

Commit Message

Alexander Graf June 15, 2018, 12:42 p.m.
With efi_loader, we may want to execute payload from RAM. By default,
permissions on the RAM region don't allow us to execute from there though.

So whenever we get into the efi_loader case, let's mark RAM as executable.
That way we still protect normal cases, but allow for efi binaries to
directly get executed from within RAM.

For this, we hook into the already existing allow_unaligned() call which
also transitions the system over into semantics required by the UEFI
specification.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/sandbox/cpu/cpu.c | 10 ++++++++++
 arch/sandbox/cpu/os.c  | 23 +++++++++++++++++++++++
 include/os.h           | 19 +++++++++++++++++++
 3 files changed, 52 insertions(+)

Patch

diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index b20894b806..944f104899 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -162,3 +162,13 @@  void longjmp(jmp_buf jmp, int ret)
 	while (1)
 		;
 }
+
+void allow_unaligned(void)
+{
+	int r;
+
+	r = os_mprotect(gd->arch.ram_buf, gd->ram_size,
+			OS_PROT_READ | OS_PROT_WRITE | OS_PROT_EXEC);
+
+	assert(!r);
+}
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 5839932b00..81206ba0d2 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -183,6 +183,29 @@  void *os_realloc(void *ptr, size_t length)
 	return buf;
 }
 
+int os_mprotect(void *ptr, size_t length, int prot)
+{
+	struct os_mem_hdr *hdr = ptr;
+	int p = 0;
+
+	if ((uintptr_t)ptr & sizeof(*hdr)) {
+		/*
+		 * We got an unaligned pointer, probably a return value
+		 * from os_malloc()
+		 */
+		ptr = &hdr[-1];
+	}
+
+	if (prot & OS_PROT_READ)
+		p |= PROT_READ;
+	if (prot & OS_PROT_WRITE)
+		p |= PROT_WRITE;
+	if (prot & OS_PROT_EXEC)
+		p |= PROT_EXEC;
+
+	return mprotect(ptr, length, p);
+}
+
 void os_usleep(unsigned long usec)
 {
 	usleep(usec);
diff --git a/include/os.h b/include/os.h
index c8e0f52d30..d451e12064 100644
--- a/include/os.h
+++ b/include/os.h
@@ -157,6 +157,25 @@  void os_free(void *ptr);
 void *os_realloc(void *ptr, size_t length);
 
 /**
+ * Modify protection of a memory region
+ *
+ * This function changes the memory protection scheme of a given memory
+ * region. Using it you can for example allow execution of memory that
+ * would otherwise prohibit it.
+ *
+ * \param ptr		Pointer to memory region to modify
+ * \param length	New length for memory block
+ * \param prot		New protection scheme (ORed OS_PROT_ values)
+ * \return 0 on success, -1 otherwise.
+ */
+int os_mprotect(void *ptr, size_t length, int prot);
+
+/* Defines for "prot" in os_mprotect() */
+#define OS_PROT_READ	0x1
+#define OS_PROT_WRITE	0x2
+#define OS_PROT_EXEC	0x4
+
+/**
  * Access to the usleep function of the os
  *
  * \param usec Time to sleep in micro seconds