[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 08/23] bsd-user: initialize stack with signal trampo
From: |
Stacey Son |
Subject: |
[Qemu-devel] [PATCH 08/23] bsd-user: initialize stack with signal trampolin code and canary |
Date: |
Sun, 23 Jun 2013 21:03:40 -0500 |
Put full path for target executable, signal trampolin code, and stack canary
on the stack in addition to just simply coping argv and env values.
Signed-off-by: Stacey Son <address@hidden>
---
bsd-user/elfload.c | 32 +++-----
bsd-user/freebsd/target_os_stack.h | 124 +++++++++++++++++++++++++++++++
bsd-user/i386/target_arch_sigtramp.h | 11 +++
bsd-user/mips/target_arch_signal.h | 2 +-
bsd-user/mips/target_arch_sigtramp.h | 23 ++++++
bsd-user/mips64/target_arch_sigtramp.h | 23 ++++++
bsd-user/netbsd/target_os_stack.h | 31 ++++++++
bsd-user/openbsd/target_os_stack.h | 31 ++++++++
bsd-user/sparc/target_arch_sigtramp.h | 11 +++
bsd-user/sparc64/target_arch_sigtramp.h | 11 +++
bsd-user/x86_64/target_arch_sigtramp.h | 11 +++
11 files changed, 289 insertions(+), 21 deletions(-)
create mode 100644 bsd-user/freebsd/target_os_stack.h
create mode 100644 bsd-user/i386/target_arch_sigtramp.h
create mode 100644 bsd-user/mips/target_arch_sigtramp.h
create mode 100644 bsd-user/mips64/target_arch_sigtramp.h
create mode 100644 bsd-user/netbsd/target_os_stack.h
create mode 100644 bsd-user/openbsd/target_os_stack.h
create mode 100644 bsd-user/sparc/target_arch_sigtramp.h
create mode 100644 bsd-user/sparc64/target_arch_sigtramp.h
create mode 100644 bsd-user/x86_64/target_arch_sigtramp.h
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 8c8ed6a..0cd5fc4 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -27,6 +27,7 @@
#include "qemu.h"
#include "disas/disas.h"
+#include "target_os_stack.h"
#ifdef _ARCH_PPC64
#undef ARCH_DLINFO
@@ -712,38 +713,29 @@ static abi_ulong copy_elf_strings(int argc,char ** argv,
void **page,
static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
struct image_info *info)
{
- abi_ulong stack_base, size, error;
- int i;
+ abi_ulong stack_base, size;
+ abi_long addr;
/* Create enough stack to hold everything. If we don't use
* it for args, we'll use it for something else...
*/
size = target_dflssiz;
stack_base = TARGET_USRSTACK - size;
- error = target_mmap(0,
- size + qemu_host_page_size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON,
- -1, 0);
- if (error == -1) {
+ addr = target_mmap(stack_base , size + qemu_host_page_size,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ if (addr == -1) {
perror("stk mmap");
exit(-1);
}
/* we reserve one extra page at the top of the stack as guard */
- target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
-
- stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
- p += stack_base;
+ target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
- for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
- if (bprm->page[i]) {
- info->rss++;
- /* FIXME - check return value of memcpy_to_target() for failure */
- memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
- g_free(bprm->page[i]);
- }
- stack_base += TARGET_PAGE_SIZE;
+ p = setup_initial_stack(p, bprm, stack_base, size, addr);
+ if (p == 0) {
+ perror("stk setup");
+ exit(-1);
}
+
return p;
}
diff --git a/bsd-user/freebsd/target_os_stack.h
b/bsd-user/freebsd/target_os_stack.h
new file mode 100644
index 0000000..f600009
--- /dev/null
+++ b/bsd-user/freebsd/target_os_stack.h
@@ -0,0 +1,124 @@
+#ifndef _TARGET_OS_STACK_H_
+#define _TARGET_OS_STACK_H_
+
+#include <sys/param.h>
+#include "target_arch_sigtramp.h"
+
+/*
+ * The inital FreeBSD stack is as follows:
+ * (see kern/kern_exec.c exec_copyout_strings() )
+ *
+ * Hi Address -> char **ps_argvstr (struct ps_strings for ps, w, etc.)
+ * unsigned ps_nargvstr
+ * char **ps_envstr
+ * PS_STRINGS -> unsigned ps_nenvstr
+ *
+ * machine dependent sigcode (sv_sigcode of size
+ * sv_szsigcode)
+ *
+ * execpath (absolute image path for rtld)
+ *
+ * SSP Canary (sizeof(long) * 8)
+ *
+ * page sizes array (usually sizeof(u_long) )
+ *
+ * "destp" -> argv, env strings (up to 262144 bytes)
+ */
+static inline abi_ulong setup_initial_stack(abi_ulong p,
+ struct bsd_binprm *bprm, abi_ulong stack_base, abi_ulong size,
+ abi_ulong addr)
+{
+ int i;
+ abi_ulong stack_hi_addr;
+ size_t execpath_len;
+ abi_ulong destp, argvp, envp;
+ struct target_ps_strings ps_strs;
+ char canary[sizeof(abi_long) * 8];
+
+ stack_hi_addr = p = addr + size;
+
+ /* Save some space for ps_strings. */
+ p -= sizeof(struct target_ps_strings);
+
+#ifdef TARGET_SZSIGCODE
+ /* Add machine depedent sigcode. */
+ p -= TARGET_SZSIGCODE;
+ if (setup_sigtramp(p, (unsigned)offsetof(struct target_sigframe, sf_uc),
+ TARGET_FREEBSD_NR_sigreturn)) {
+ return 0;
+ }
+#endif
+ if (bprm->fullpath) {
+ execpath_len = strlen(bprm->fullpath) + 1;
+ p -= roundup(execpath_len, sizeof(abi_ulong));
+ if (memcpy_to_target(p, bprm->fullpath, execpath_len)) {
+ return 0;
+ }
+ }
+ /* Add canary for SSP. */
+ arc4random_buf(canary, sizeof(canary));
+ p -= roundup(sizeof(canary), sizeof(abi_ulong));
+ if (memcpy_to_target(p, canary, sizeof(canary))) {
+ return 0;
+ }
+ /* Add page sizes array. */
+ p -= sizeof(abi_ulong);
+ if (put_user_ual(TARGET_PAGE_SIZE, p)) {
+ return 0;
+ }
+ argvp = p - TARGET_SPACE_USRSPACE;
+ p = destp = p - TARGET_SPACE_USRSPACE - TARGET_ARG_MAX;
+ /* XXX check strlen(argv and envp strings) < TARGET_ARG_MAX ? */
+
+ /*
+ * Add argv strings. Note that the argv[] vectors are added by
+ * loader_build_argptr()
+ */
+ envp = argvp + (bprm->argc + 2) * sizeof(abi_ulong);
+ ps_strs.ps_argvstr = tswapl(argvp);
+ ps_strs.ps_nargvstr = tswap32(bprm->argc);
+ for (i = 0; i < bprm->argc; ++i) {
+ size_t len = strlen(bprm->argv[i]) + 1;
+
+ if (memcpy_to_target(destp, bprm->argv[i], len)) {
+ return 0;
+ }
+ if (put_user_ual(destp, argvp)) {
+ return 0;
+ }
+ argvp += sizeof(abi_ulong);
+ destp += len;
+ }
+ if (put_user_ual(0, argvp)) {
+ return 0;
+ }
+ /*
+ * Add env strings. Note that the envp[] vectors are added by
+ * loader_build_argptr().
+ */
+ ps_strs.ps_envstr = tswapl(envp);
+ ps_strs.ps_nenvstr = tswap32(bprm->envc);
+ for (i = 0; i < bprm->envc; ++i) {
+ size_t len = strlen(bprm->envp[i]) + 1;
+
+ if (memcpy_to_target(destp, bprm->envp[i], len)) {
+ return 0;
+ }
+ if (put_user_ual(destp, envp)) {
+ return 0;
+ }
+ envp += sizeof(abi_ulong);
+ destp += len;
+ }
+ if (put_user_ual(0, envp)) {
+ return 0;
+ }
+ if (memcpy_to_target(stack_hi_addr - sizeof(ps_strs), &ps_strs,
+ sizeof(ps_strs))) {
+ return 0;
+ }
+
+ return p;
+ }
+
+#endif /* !_TARGET_OS_STACK_H_ */
diff --git a/bsd-user/i386/target_arch_sigtramp.h
b/bsd-user/i386/target_arch_sigtramp.h
new file mode 100644
index 0000000..f0f36d1
--- /dev/null
+++ b/bsd-user/i386/target_arch_sigtramp.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+ unsigned sys_sigreturn)
+{
+
+ return -TARGET_EOPNOTSUPP;
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/mips/target_arch_signal.h
b/bsd-user/mips/target_arch_signal.h
index cc7e750..f68034f 100644
--- a/bsd-user/mips/target_arch_signal.h
+++ b/bsd-user/mips/target_arch_signal.h
@@ -22,7 +22,7 @@
#define TARGET_INSN_SIZE 4 /* mips instruction size */
-/* Size of the signal trampolin code placed on the stack. */
+/* Size of the signal trampolin code. See insall_sigtramp(). */
#define TARGET_SZSIGCODE ((abi_ulong)(4 * TARGET_INSN_SIZE))
/* compare to mips/include/_limits.h */
diff --git a/bsd-user/mips/target_arch_sigtramp.h
b/bsd-user/mips/target_arch_sigtramp.h
new file mode 100644
index 0000000..5e3c69a
--- /dev/null
+++ b/bsd-user/mips/target_arch_sigtramp.h
@@ -0,0 +1,23 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+/* Compare to mips/mips/locore.S sigcode() */
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+ unsigned sys_sigreturn)
+{
+ int i;
+ uint32_t sigtramp_code[TARGET_SZSIGCODE/TARGET_INSN_SIZE] = {
+ /* 1 */ 0x67A40000 + sigf_uc, /* daddu $a0, $sp, (sigf_uc) */
+ /* 2 */ 0x24020000 + sys_sigreturn, /* li $v0, (sys_sigreturn) */
+ /* 3 */ 0x0000000C, /* syscall */
+ /* 4 */ 0x0000000D /* break */
+ };
+
+ for (i = 0; i < 4; i++) {
+ tswap32s(&sigtramp_code[i]);
+ }
+
+ return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/mips64/target_arch_sigtramp.h
b/bsd-user/mips64/target_arch_sigtramp.h
new file mode 100644
index 0000000..5e3c69a
--- /dev/null
+++ b/bsd-user/mips64/target_arch_sigtramp.h
@@ -0,0 +1,23 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+/* Compare to mips/mips/locore.S sigcode() */
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+ unsigned sys_sigreturn)
+{
+ int i;
+ uint32_t sigtramp_code[TARGET_SZSIGCODE/TARGET_INSN_SIZE] = {
+ /* 1 */ 0x67A40000 + sigf_uc, /* daddu $a0, $sp, (sigf_uc) */
+ /* 2 */ 0x24020000 + sys_sigreturn, /* li $v0, (sys_sigreturn) */
+ /* 3 */ 0x0000000C, /* syscall */
+ /* 4 */ 0x0000000D /* break */
+ };
+
+ for (i = 0; i < 4; i++) {
+ tswap32s(&sigtramp_code[i]);
+ }
+
+ return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/netbsd/target_os_stack.h
b/bsd-user/netbsd/target_os_stack.h
new file mode 100644
index 0000000..a852ae6
--- /dev/null
+++ b/bsd-user/netbsd/target_os_stack.h
@@ -0,0 +1,31 @@
+#ifndef _TARGET_OS_STACK_H_
+#define _TARGET_OS_STACK_H_
+
+#include "target_arch_sigtramp.h"
+
+static inline abi_ulong setup_initial_stack(abi_ulong p,
+ struct bsd_binprm *bprm, abi_ulong sbase, abi_ulong size,
+ abi_ulong addr)
+{
+ int i;
+ abi_ulong stack_base;
+
+ stack_base = addr + size - MAX_ARG_PAGES * TARGET_PAGE_SIZE;
+ p += stack_base;
+
+ for (i = 0; i < MAX_ARG_PAGES; i++) {
+ if (bprm->page[i]) {
+ info->rss++;
+ if (!memcpy_to_target(stack_base, bprm->page[i],
+ TARGET_PAGE_SIZE)) {
+ return 0;
+ }
+ g_free(bprm->page[i]);
+ }
+ stack_base += TARGET_PAGE_SIZE;
+ }
+
+ return p;
+}
+
+#endif /* !_TARGET_OS_STACK_H_ */
diff --git a/bsd-user/openbsd/target_os_stack.h
b/bsd-user/openbsd/target_os_stack.h
new file mode 100644
index 0000000..a852ae6
--- /dev/null
+++ b/bsd-user/openbsd/target_os_stack.h
@@ -0,0 +1,31 @@
+#ifndef _TARGET_OS_STACK_H_
+#define _TARGET_OS_STACK_H_
+
+#include "target_arch_sigtramp.h"
+
+static inline abi_ulong setup_initial_stack(abi_ulong p,
+ struct bsd_binprm *bprm, abi_ulong sbase, abi_ulong size,
+ abi_ulong addr)
+{
+ int i;
+ abi_ulong stack_base;
+
+ stack_base = addr + size - MAX_ARG_PAGES * TARGET_PAGE_SIZE;
+ p += stack_base;
+
+ for (i = 0; i < MAX_ARG_PAGES; i++) {
+ if (bprm->page[i]) {
+ info->rss++;
+ if (!memcpy_to_target(stack_base, bprm->page[i],
+ TARGET_PAGE_SIZE)) {
+ return 0;
+ }
+ g_free(bprm->page[i]);
+ }
+ stack_base += TARGET_PAGE_SIZE;
+ }
+
+ return p;
+}
+
+#endif /* !_TARGET_OS_STACK_H_ */
diff --git a/bsd-user/sparc/target_arch_sigtramp.h
b/bsd-user/sparc/target_arch_sigtramp.h
new file mode 100644
index 0000000..f0f36d1
--- /dev/null
+++ b/bsd-user/sparc/target_arch_sigtramp.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+ unsigned sys_sigreturn)
+{
+
+ return -TARGET_EOPNOTSUPP;
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/sparc64/target_arch_sigtramp.h
b/bsd-user/sparc64/target_arch_sigtramp.h
new file mode 100644
index 0000000..f0f36d1
--- /dev/null
+++ b/bsd-user/sparc64/target_arch_sigtramp.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+ unsigned sys_sigreturn)
+{
+
+ return -TARGET_EOPNOTSUPP;
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/x86_64/target_arch_sigtramp.h
b/bsd-user/x86_64/target_arch_sigtramp.h
new file mode 100644
index 0000000..f0f36d1
--- /dev/null
+++ b/bsd-user/x86_64/target_arch_sigtramp.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+ unsigned sys_sigreturn)
+{
+
+ return -TARGET_EOPNOTSUPP;
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
--
1.7.8
- [Qemu-devel] [PATCH 00/23] bsd-user: FreeBSD support for mips/mips64 and arm, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 07/23] bsd-user: find target executable in path when absolute path not given, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 05/23] bsd-user: add bsd_binprm to TaskState for core dumping emulation, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 06/23] bsd-user: fix thread initialization and ELF addresses for mips/mips64, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 13/23] bsd-user: add shims for signal related system calls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 08/23] bsd-user: initialize stack with signal trampolin code and canary,
Stacey Son <=
- [Qemu-devel] [PATCH 02/23] bsd-user: add initial support for mips/mips64, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 01/23] bsd-user: initial code clean up, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 11/23] bsd-user: add shims for file related system calls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 10/23] bsd-user: add shims for memory management related syscalls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 09/23] bsd-user: refresh FreeBSD's system call numbers, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 12/23] bsd-user: add shims for time related system calls., Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 03/23] bsd-user: additional seperation of OS and architecture dependent code, Stacey Son, 2013/06/24