Re: [Qemu-devel] [PATCH] linux-user sigaltstack() syscall
On Mon, 2007-09-24 at 23:04 -0600, Thayne Harbaugh wrote: This patch adds the sigaltstack() syscall for linux-user. The previous patch relied on the EFAULT patch, this newer version does not. It also fixes a few places that used tswap32() that should use __put_user(). Index: qemu/linux-user/signal.c === --- qemu.orig/linux-user/signal.c 2007-09-25 05:46:34.0 -0600 +++ qemu/linux-user/signal.c 2007-09-25 06:35:23.0 -0600 @@ -26,6 +26,7 @@ #include errno.h #include sys/ucontext.h +#include target_signal.h #include qemu.h //#define DEBUG_SIGNAL @@ -45,6 +46,12 @@ first signal, we put it here */ }; +struct target_sigaltstack target_sigaltstack_used = { +.ss_sp = 0, +.ss_size = 0, +.ss_flags = TARGET_SS_DISABLE, +}; + static struct emulated_sigaction sigact_table[TARGET_NSIG]; static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */ static struct sigqueue *first_free; /* first free siginfo queue entry */ @@ -92,6 +99,18 @@ }; static uint8_t target_to_host_signal_table[65]; +static inline int on_sig_stack(unsigned long sp) +{ +return (sp - target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size); +} + +static inline int sas_ss_flags(unsigned long sp) +{ +return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE +: on_sig_stack(sp) ? SS_ONSTACK : 0); +} + static inline int host_to_target_signal(int sig) { return host_to_target_signal_table[sig]; @@ -419,6 +438,67 @@ } } +int do_sigaltstack(const struct target_sigaltstack *uss, + struct target_sigaltstack *uoss, + target_ulong sp) +{ +int ret; +struct target_sigaltstack oss; + +/* XXX: test errors */ +if(uoss) +{ +__put_user(target_sigaltstack_used.ss_sp, oss.ss_sp); +__put_user(target_sigaltstack_used.ss_size, oss.ss_size); +__put_user(sas_ss_flags(sp), oss.ss_flags); +} + +if(uss) +{ + struct target_sigaltstack ss; + + ret = -EFAULT; + if (!access_ok(VERIFY_READ, uss, sizeof(*uss)) + || __get_user(ss.ss_sp, uss-ss_sp) + || __get_user(ss.ss_size, uss-ss_size) + || __get_user(ss.ss_flags, uss-ss_flags)) +goto out; + + ret = -EPERM; + if (on_sig_stack(sp)) +goto out; + + ret = -EINVAL; + if (ss.ss_flags != TARGET_SS_DISABLE + ss.ss_flags != TARGET_SS_ONSTACK + ss.ss_flags != 0) +goto out; + + if (ss.ss_flags == TARGET_SS_DISABLE) { +ss.ss_size = 0; +ss.ss_sp = 0; + } else { +ret = -ENOMEM; +if (ss.ss_size MINSIGSTKSZ) +goto out; + } + +target_sigaltstack_used.ss_sp = ss.ss_sp; +target_sigaltstack_used.ss_size = ss.ss_size; +} + +if (uoss) { +ret = -EFAULT; +if (!access_ok(VERIFY_WRITE, uoss, sizeof(oss))) +goto out; +memcpy(uoss, oss, sizeof(oss)); +} + +ret = 0; +out: +return ret; +} + int do_sigaction(int sig, const struct target_sigaction *act, struct target_sigaction *oact) { @@ -551,12 +631,6 @@ target_ulong cr2; }; -typedef struct target_sigaltstack { - target_ulong ss_sp; - int ss_flags; - target_ulong ss_size; -} target_stack_t; - struct target_ucontext { target_ulong tuc_flags; target_ulong tuc_link; @@ -640,16 +714,14 @@ /* Default to using normal stack */ esp = env-regs[R_ESP]; -#if 0 /* This is the X/Open sanctioned signal stack switching. */ - if (ka-sa.sa_flags SA_ONSTACK) { - if (sas_ss_flags(esp) == 0) - esp = current-sas_ss_sp + current-sas_ss_size; - } +if (ka-sa.sa_flags TARGET_SA_ONSTACK) { +if (sas_ss_flags(esp) == 0) +esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +} /* This is the legacy signal stack switching. */ else -#endif if ((env-segs[R_SS].selector 0x) != __USER_DS !(ka-sa.sa_flags TARGET_SA_RESTORER) ka-sa.sa_restorer) { @@ -750,11 +822,11 @@ /* Create the ucontext. */ err |= __put_user(0, frame-uc.tuc_flags); err |= __put_user(0, frame-uc.tuc_link); - err |= __put_user(/*current-sas_ss_sp*/ 0, + err |= __put_user(target_sigaltstack_used.ss_sp, frame-uc.tuc_stack.ss_sp); - err |= __put_user(/* sas_ss_flags(regs-esp) */ 0, + err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)), frame-uc.tuc_stack.ss_flags); - err |= __put_user(/* current-sas_ss_size */ 0, + err |= __put_user(target_sigaltstack_used.ss_size, frame-uc.tuc_stack.ss_size); err |= setup_sigcontext(frame-uc.tuc_mcontext, frame-fpstate, env, set-sig[0]); @@ -880,7 +952,6 @@ { struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env-regs[R_ESP] - 4); sigset_t set; -// stack_t st; int eax; #if 0 @@ -893,13 +964,9 @@ if
[Qemu-devel] [PATCH] linux-user sigaltstack() syscall
This patch adds the sigaltstack() syscall for linux-user. Index: qemu/linux-user/signal.c === --- qemu.orig/linux-user/signal.c 2007-09-24 22:45:48.0 -0600 +++ qemu/linux-user/signal.c 2007-09-24 22:56:18.0 -0600 @@ -26,6 +26,7 @@ #include errno.h #include sys/ucontext.h +#include target_signal.h #include qemu.h /* @@ -51,6 +52,12 @@ first signal, we put it here */ }; +struct target_sigaltstack target_sigaltstack_used = { +.ss_sp = 0, +.ss_size = 0, +.ss_flags = TARGET_SS_DISABLE, +}; + static struct emulated_sigaction sigact_table[TARGET_NSIG]; static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */ static struct sigqueue *first_free; /* first free siginfo queue entry */ @@ -98,6 +105,18 @@ }; static uint8_t target_to_host_signal_table[65]; +static inline int on_sig_stack(unsigned long sp) +{ +return (sp - target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size); +} + +static inline int sas_ss_flags(unsigned long sp) +{ +return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE +: on_sig_stack(sp) ? SS_ONSTACK : 0); +} + static inline int host_to_target_signal(int sig) { return host_to_target_signal_table[sig]; @@ -420,6 +439,66 @@ } } +int do_sigaltstack(const struct target_sigaltstack *uss, + struct target_sigaltstack *uoss, + target_ulong sp) +{ +int ret; +struct target_sigaltstack oss; + +/* XXX: test errors */ +if(uoss) +{ +oss.ss_sp = tswap32(target_sigaltstack_used.ss_sp); +oss.ss_size = tswap32(target_sigaltstack_used.ss_size); +oss.ss_flags = tswap32(sas_ss_flags(sp)); +} + +if(uss) +{ + struct target_sigaltstack ss; + + ret = -EFAULT; + if (!access_ok(VERIFY_READ, uss, sizeof(*uss)) + || __get_user(ss.ss_sp, uss-ss_sp) + || __get_user(ss.ss_size, uss-ss_size) + || __get_user(ss.ss_flags, uss-ss_flags)) +goto out; + + ret = -EPERM; + if (on_sig_stack(sp)) +goto out; + + ret = -EINVAL; + if (ss.ss_flags != TARGET_SS_DISABLE + ss.ss_flags != TARGET_SS_ONSTACK + ss.ss_flags != 0) +goto out; + + if (ss.ss_flags == TARGET_SS_DISABLE) { +ss.ss_size = 0; +ss.ss_sp = 0; + } else { +ret = -ENOMEM; +if (ss.ss_size MINSIGSTKSZ) +goto out; + } + +target_sigaltstack_used.ss_sp = ss.ss_sp; +target_sigaltstack_used.ss_size = ss.ss_size; +} + +if (uoss) { +ret = -EFAULT; +if (copy_to_user(uoss, oss, sizeof(oss))) +goto out; +} + +ret = 0; +out: +return ret; +} + int do_sigaction(int sig, const struct target_sigaction *act, struct target_sigaction *oact) { @@ -550,12 +629,6 @@ target_ulong cr2; }; -typedef struct target_sigaltstack { - target_ulong ss_sp; - int ss_flags; - target_ulong ss_size; -} target_stack_t; - struct target_ucontext { target_ulong tuc_flags; target_ulong tuc_link; @@ -639,16 +712,14 @@ /* Default to using normal stack */ esp = env-regs[R_ESP]; -#if 0 /* This is the X/Open sanctioned signal stack switching. */ - if (ka-sa.sa_flags SA_ONSTACK) { - if (sas_ss_flags(esp) == 0) - esp = current-sas_ss_sp + current-sas_ss_size; - } +if (ka-sa.sa_flags TARGET_SA_ONSTACK) { +if (sas_ss_flags(esp) == 0) +esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +} /* This is the legacy signal stack switching. */ else -#endif if ((env-segs[R_SS].selector 0x) != __USER_DS !(ka-sa.sa_flags TARGET_SA_RESTORER) ka-sa.sa_restorer) { @@ -749,11 +820,11 @@ /* Create the ucontext. */ err |= __put_user(0, frame-uc.tuc_flags); err |= __put_user(0, frame-uc.tuc_link); - err |= __put_user(/*current-sas_ss_sp*/ 0, + err |= __put_user(target_sigaltstack_used.ss_sp, frame-uc.tuc_stack.ss_sp); - err |= __put_user(/* sas_ss_flags(regs-esp) */ 0, + err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)), frame-uc.tuc_stack.ss_flags); - err |= __put_user(/* current-sas_ss_size */ 0, + err |= __put_user(target_sigaltstack_used.ss_size, frame-uc.tuc_stack.ss_size); err |= setup_sigcontext(frame-uc.tuc_mcontext, frame-fpstate, env, set-sig[0]); @@ -877,7 +948,6 @@ { struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env-regs[R_ESP] - 4); sigset_t set; -// stack_t st; int eax; #if 0 @@ -890,13 +960,9 @@ if (restore_sigcontext(env, frame-uc.tuc_mcontext, eax)) goto badframe; -#if 0 - if (__copy_from_user(st, frame-uc.tuc_stack, sizeof(st))) + if (do_sigaltstack(frame-uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT) goto badframe; - /* It is more difficult to avoid calling this