]> Git Repo - qemu.git/commitdiff
Usermode exec-stack fix
authorPaul Brook <[email protected]>
Wed, 16 Jun 2010 12:03:51 +0000 (13:03 +0100)
committerPaul Brook <[email protected]>
Wed, 16 Jun 2010 12:03:51 +0000 (13:03 +0100)
When loading a shared library that requires an executable stack,
glibc uses the mprotext PROT_GROWSDOWN flag to achieve this.
We don't support PROT_GROWSDOWN.
Add a special case to handle changing the stack permissions in this way.

Signed-off-by: Paul Brook <[email protected]>
linux-user/elfload.c
linux-user/flatload.c
linux-user/qemu.h
linux-user/syscall.c

index 2d920f2017e3150dafab403b7c68f0cc8afdcace..accb44d9ded74782e8b6fb71f4d36d823e7a97a8 100644 (file)
@@ -1018,6 +1018,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
     /* we reserve one extra page at the top of the stack as guard */
     target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
 
+    info->stack_limit = error;
     stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
     p += stack_base;
 
index 914de1f8885dda297aed8aac5574543eeb4bf71e..8ad130a2bd8da969ef604e9ab17cf7ba0e5e35e7 100644 (file)
@@ -802,6 +802,7 @@ int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     info->end_data = libinfo[0].end_data;
     info->start_brk = libinfo[0].start_brk;
     info->start_stack = sp;
+    info->stack_limit = libinfo[0].start_brk;
     info->entry = start_addr;
     info->code_offset = info->start_code;
     info->data_offset = info->start_data - libinfo[0].text_len;
index dab3597cc6703bcb3ac5f832a7ba708dbb438070..1878d5a61e96423aa1ccde6fd32ffafe05b995b3 100644 (file)
@@ -42,6 +42,7 @@ struct image_info {
         abi_ulong       mmap;
         abi_ulong       rss;
         abi_ulong       start_stack;
+        abi_ulong       stack_limit;
         abi_ulong       entry;
         abi_ulong       code_offset;
         abi_ulong       data_offset;
index e94f1eed5c85674ef3365f2044cc7cf06921006a..0ebe7e1c2695f6c0f92523e0cbcdf1128ae41388 100644 (file)
@@ -5400,6 +5400,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = get_errno(target_munmap(arg1, arg2));
         break;
     case TARGET_NR_mprotect:
+        {
+            TaskState *ts = ((CPUState *)cpu_env)->opaque;
+            /* Special hack to detect libc making the stack executable.  */
+            if ((arg3 & PROT_GROWSDOWN)
+                && arg1 >= ts->info->stack_limit
+                && arg1 <= ts->info->start_stack) {
+                arg3 &= ~PROT_GROWSDOWN;
+                arg2 = arg2 + arg1 - ts->info->stack_limit;
+                arg1 = ts->info->stack_limit;
+            }
+        }
         ret = get_errno(target_mprotect(arg1, arg2, arg3));
         break;
 #ifdef TARGET_NR_mremap
This page took 0.045799 seconds and 4 git commands to generate.