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.
273 lines
8.1 KiB
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);
|