You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gentoo-overlay/sys-apps/proot/files/proot-5.1.0-loader.patch

273 lines
8.1 KiB

commit 77d5ba4e5bb35f91d026a3240ad0a91a2d4b662a
Author: Cédric VINCENT <cedric.vincent@st.com>
Date: Fri Feb 20 14:28:55 2015 +0100
Set tracee's stack executable when the loaded program requires this.
This is required for UMEQ and for some older versions of PRoot. For
example:
$ proot -q umeq-arm64-dce01957 -R ~/gentoo-arm64-20140718
Before:
proot info: vpid 1 terminated with signal 11
Now, it is OK.
diff --git a/src/compat.h b/src/compat.h
index 2b603f1..5009490 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -243,5 +243,17 @@
# ifndef MAP_ANONYMOUS
# define MAP_ANONYMOUS 0x20
# endif
+# ifndef PROT_READ
+# define PROT_READ 0x1
+# endif
+# ifndef PROT_WRITE
+# define PROT_WRITE 0x2
+# endif
+# ifndef PROT_EXEC
+# define PROT_EXEC 0x4
+# endif
+# ifndef PROT_GROWSDOWN
+# define PROT_GROWSDOWN 0x01000000
+# endif
#endif /* COMPAT_H */
diff --git a/src/execve/elf.h b/src/execve/elf.h
index 3ced10c..a5b367b 100644
--- a/src/execve/elf.h
+++ b/src/execve/elf.h
@@ -108,7 +108,8 @@ typedef union {
typedef enum {
PT_LOAD = 1,
PT_DYNAMIC = 2,
- PT_INTERP = 3
+ PT_INTERP = 3,
+ PT_GNU_STACK = 0x6474e551,
} SegmentType;
typedef struct {
diff --git a/src/execve/enter.c b/src/execve/enter.c
index cb84ec6..f0f3e7f 100644
--- a/src/execve/enter.c
+++ b/src/execve/enter.c
@@ -252,6 +252,11 @@ static int add_load_info(const ElfHeader *elf_header,
return status;
break;
+ case PT_GNU_STACK:
+ data->load_info->needs_executable_stack |=
+ ((PROGRAM_FIELD(*elf_header, *program_header, flags) & PF_X) != 0);
+ break;
+
default:
break;
}
diff --git a/src/execve/execve.h b/src/execve/execve.h
index 11eca10..98b8d03 100644
--- a/src/execve/execve.h
+++ b/src/execve/execve.h
@@ -49,6 +49,7 @@ typedef struct load_info {
char *raw_path;
Mapping *mappings;
ElfHeader elf_header;
+ bool needs_executable_stack;
struct load_info *interp;
} LoadInfo;
diff --git a/src/execve/exit.c b/src/execve/exit.c
index e6eff44..36cc51f 100644
--- a/src/execve/exit.c
+++ b/src/execve/exit.c
@@ -174,6 +174,9 @@ static void *transcript_mappings(void *cursor, const Mapping *mappings)
static int transfer_load_script(Tracee *tracee)
{
const word_t stack_pointer = peek_reg(tracee, CURRENT, STACK_POINTER);
+ static word_t page_size = 0;
+ static word_t page_mask = 0;
+
word_t entry_point;
size_t script_size;
@@ -190,10 +193,22 @@ static int transfer_load_script(Tracee *tracee)
void *buffer;
size_t buffer_size;
+ bool needs_executable_stack;
LoadStatement *statement;
void *cursor;
int status;
+ if (page_size == 0) {
+ page_size = sysconf(_SC_PAGE_SIZE);
+ if ((int) page_size <= 0)
+ page_size = 0x1000;
+ page_mask = ~(page_size - 1);
+ }
+
+ needs_executable_stack = (tracee->load_info->needs_executable_stack
+ || ( tracee->load_info->interp != NULL
+ && tracee->load_info->interp->needs_executable_stack));
+
/* Strings addresses are required to generate the load script,
* for "open" actions. Since I want to generate it in one
* pass, these strings will be put right below the current
@@ -208,7 +223,7 @@ static int transfer_load_script(Tracee *tracee)
: strlen(tracee->load_info->raw_path) + 1);
/* A padding will be appended at the end of the load script
- * (a.k.a "strings area") to ensure this latter is aligned on
+ * (a.k.a "strings area") to ensure this latter is aligned to
* a word boundary, for sake of performance. */
padding_size = (stack_pointer - string1_size - string2_size - string3_size)
% sizeof_word(tracee);
@@ -229,6 +244,7 @@ static int transfer_load_script(Tracee *tracee)
: LOAD_STATEMENT_SIZE(*statement, open)
+ (LOAD_STATEMENT_SIZE(*statement, mmap)
* talloc_array_length(tracee->load_info->interp->mappings)))
+ + (needs_executable_stack ? LOAD_STATEMENT_SIZE(*statement, make_stack_exec) : 0)
+ LOAD_STATEMENT_SIZE(*statement, start);
/* Allocate enough room for both the load script and the
@@ -266,6 +282,16 @@ static int transfer_load_script(Tracee *tracee)
else
entry_point = ELF_FIELD(tracee->load_info->elf_header, entry);
+ if (needs_executable_stack) {
+ /* Load script statement: stack_exec. */
+ statement = cursor;
+
+ statement->action = LOAD_ACTION_MAKE_STACK_EXEC;
+ statement->make_stack_exec.start = stack_pointer & page_mask;
+
+ cursor += LOAD_STATEMENT_SIZE(*statement, make_stack_exec);
+ }
+
/* Load script statement: start. */
statement = cursor;
@@ -352,7 +378,7 @@ static int transfer_load_script(Tracee *tracee)
* | mmap file |
* +------------+
* | open |
- * +------------+ <- stack pointer, sysarg1 (word aligned)
+ * +------------+ <- stack pointer, userarg1 (word aligned)
*/
/* Remember we are in the sysexit stage, so be sure the
diff --git a/src/loader/assembly-arm.h b/src/loader/assembly-arm.h
index ee5bb85..59a7fe0 100644
--- a/src/loader/assembly-arm.h
+++ b/src/loader/assembly-arm.h
@@ -89,4 +89,5 @@
#define EXECVE 11
#define EXIT 1
#define PRCTL 172
+#define MPROTECT 125
diff --git a/src/loader/assembly-x86.h b/src/loader/assembly-x86.h
index c83b3ef..4045144 100644
--- a/src/loader/assembly-x86.h
+++ b/src/loader/assembly-x86.h
@@ -65,3 +65,4 @@ extern word_t syscall_1(word_t number, word_t arg1);
#define EXECVE 11
#define EXIT 1
#define PRCTL 172
+#define MPROTECT 125
diff --git a/src/loader/assembly-x86_64.h b/src/loader/assembly-x86_64.h
index c581208..6f431be 100644
--- a/src/loader/assembly-x86_64.h
+++ b/src/loader/assembly-x86_64.h
@@ -93,3 +93,4 @@
#define EXECVE 59
#define EXIT 60
#define PRCTL 157
+#define MPROTECT 10
diff --git a/src/loader/loader.c b/src/loader/loader.c
index 5b31b02..9c2037b 100644
--- a/src/loader/loader.c
+++ b/src/loader/loader.c
@@ -171,6 +171,14 @@ void _start(void *cursor)
cursor += LOAD_STATEMENT_SIZE(*stmt, mmap);
break;
+ case LOAD_ACTION_MAKE_STACK_EXEC:
+ SYSCALL(MPROTECT, 3,
+ stmt->make_stack_exec.start, 1,
+ PROT_READ | PROT_WRITE | PROT_EXEC | PROT_GROWSDOWN);
+
+ cursor += LOAD_STATEMENT_SIZE(*stmt, make_stack_exec);
+ break;
+
case LOAD_ACTION_START_TRACED:
traced = true;
/* Fall through. */
diff --git a/src/loader/script.h b/src/loader/script.h
index bb48af5..6ae7621 100644
--- a/src/loader/script.h
+++ b/src/loader/script.h
@@ -42,6 +42,10 @@ struct load_statement {
word_t clear_length;
} mmap;
+ struct {
+ word_t start;
+ } make_stack_exec;
+
struct {
word_t stack_pointer;
word_t entry_point;
@@ -67,7 +71,8 @@ typedef struct load_statement LoadStatement;
#define LOAD_ACTION_OPEN 1
#define LOAD_ACTION_MMAP_FILE 2
#define LOAD_ACTION_MMAP_ANON 3
-#define LOAD_ACTION_START_TRACED 4
-#define LOAD_ACTION_START 5
+#define LOAD_ACTION_MAKE_STACK_EXEC 4
+#define LOAD_ACTION_START_TRACED 5
+#define LOAD_ACTION_START 6
#endif /* SCRIPT */
commit d649854ddb66779950954aac99d960379c631a71
Author: Nicolas Cornu <ncornu@aldebaran.com>
Date: Wed Jul 29 14:52:57 2015 +0200
Fix use of size
diff --git a/src/execve/enter.c b/src/execve/enter.c
index 8f22d9c..4c163a1 100644
--- a/src/execve/enter.c
+++ b/src/execve/enter.c
@@ -454,10 +454,10 @@ static int expand_runner(Tracee* tracee, char host_path[PATH_MAX], char user_pat
}
extern unsigned char _binary_loader_exe_start;
-extern unsigned char _binary_loader_exe_size;
+extern unsigned char _binary_loader_exe_end;
extern unsigned char WEAK _binary_loader_m32_exe_start;
-extern unsigned char WEAK _binary_loader_m32_exe_size;
+extern unsigned char WEAK _binary_loader_m32_exe_end;
/**
* Extract the built-in loader. This function returns NULL if an
@@ -483,11 +483,11 @@ static char *extract_loader(const Tracee *tracee, bool wants_32bit_version)
if (wants_32bit_version) {
start = (void *) &_binary_loader_m32_exe_start;
- size = (size_t) &_binary_loader_m32_exe_size;
+ size = (size_t)(&_binary_loader_m32_exe_end-&_binary_loader_m32_exe_start);
}
else {
start = (void *) &_binary_loader_exe_start;
- size = (size_t) &_binary_loader_exe_size;
+ size = (size_t) (&_binary_loader_exe_end-&_binary_loader_exe_start);
}
status2 = write(fd, start, size);