__u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
struct sigcontext32 sc;
_sigregs32 sregs;
+ int signo;
__u8 retcode[S390_SYSCALL_SIZE];
} sigframe32;
{
__u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
__u8 retcode[S390_SYSCALL_SIZE];
- struct siginfo32 info;
+ compat_siginfo_t info;
struct ucontext32 uc;
} rt_sigframe32;
asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
-int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
{
int err;
- if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+ if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
return -EFAULT;
/* If you change siginfo_t structure, please be sure
&to->si_addr);
break;
case __SI_POLL >> 16:
- case __SI_TIMER >> 16:
err |= __put_user(from->si_band, &to->si_band);
err |= __put_user(from->si_fd, &to->si_fd);
break;
+ case __SI_TIMER >> 16:
+ err |= __put_user(from->si_tid, &to->si_tid);
+ err |= __put_user(from->si_overrun, &to->si_overrun);
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+ default:
+ break;
+ }
+ }
+ return err;
+}
+
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
+{
+ int err;
+ u32 tmp;
+
+ if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
+ return -EFAULT;
+
+ err = __get_user(to->si_signo, &from->si_signo);
+ err |= __get_user(to->si_errno, &from->si_errno);
+ err |= __get_user(to->si_code, &from->si_code);
+
+ if (to->si_code < 0)
+ err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+ else {
+ switch (to->si_code >> 16) {
+ case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
+ case __SI_MESGQ >> 16:
+ err |= __get_user(to->si_int, &from->si_int);
+ /* fallthrough */
+ case __SI_KILL >> 16:
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ break;
+ case __SI_CHLD >> 16:
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ err |= __get_user(to->si_utime, &from->si_utime);
+ err |= __get_user(to->si_stime, &from->si_stime);
+ err |= __get_user(to->si_status, &from->si_status);
+ break;
+ case __SI_FAULT >> 16:
+ err |= __get_user(tmp, &from->si_addr);
+ to->si_addr = (void *)(u64) (tmp & PSW32_ADDR_INSN);
+ break;
+ case __SI_POLL >> 16:
+ err |= __get_user(to->si_band, &from->si_band);
+ err |= __get_user(to->si_fd, &from->si_fd);
+ break;
+ case __SI_TIMER >> 16:
+ err |= __get_user(to->si_tid, &from->si_tid);
+ err |= __get_user(to->si_overrun, &from->si_overrun);
+ err |= __get_user(to->si_int, &from->si_int);
+ break;
default:
break;
}
struct old_sigaction32 __user *oact)
{
struct k_sigaction new_ka, old_ka;
+ unsigned long sa_handler, sa_restorer;
int ret;
if (act) {
compat_old_sigset_t mask;
if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
- __get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user((unsigned long)new_ka.sa.sa_restorer, &act->sa_restorer))
+ __get_user(sa_handler, &act->sa_handler) ||
+ __get_user(sa_restorer, &act->sa_restorer))
return -EFAULT;
+ new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
+ new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer;
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
__get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask);
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
+ sa_handler = (unsigned long) old_ka.sa.sa_handler;
+ sa_restorer = (unsigned long) old_ka.sa.sa_restorer;
if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user((unsigned long)old_ka.sa.sa_restorer, &oact->sa_restorer))
+ __put_user(sa_handler, &oact->sa_handler) ||
+ __put_user(sa_restorer, &oact->sa_restorer))
return -EFAULT;
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
struct sigaction32 __user *oact, size_t sigsetsize)
{
struct k_sigaction new_ka, old_ka;
+ unsigned long sa_handler;
int ret;
compat_sigset_t set32;
return -EINVAL;
if (act) {
- ret = get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler);
+ ret = get_user(sa_handler, &act->sa_handler);
ret |= __copy_from_user(&set32, &act->sa_mask,
sizeof(compat_sigset_t));
switch (_NSIG_WORDS) {
if (ret)
return -EFAULT;
+ new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
}
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
struct pt_regs *regs)
{
stack_t kss, koss;
+ unsigned long ss_sp;
int ret, err = 0;
mm_segment_t old_fs = get_fs();
if (uss) {
if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
return -EFAULT;
- err |= __get_user((unsigned long) kss.ss_sp, &uss->ss_sp);
+ err |= __get_user(ss_sp, &uss->ss_sp);
err |= __get_user(kss.ss_size, &uss->ss_size);
err |= __get_user(kss.ss_flags, &uss->ss_flags);
if (err)
return -EFAULT;
+ kss.ss_sp = (void *) ss_sp;
}
set_fs (KERNEL_DS);
if (!ret && uoss) {
if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
return -EFAULT;
- err |= __put_user((unsigned long) koss.ss_sp, &uoss->ss_sp);
+ ss_sp = (unsigned long) koss.ss_sp;
+ err |= __put_user(ss_sp, &uoss->ss_sp);
err |= __put_user(koss.ss_size, &uoss->ss_size);
err |= __put_user(koss.ss_flags, &uoss->ss_flags);
if (err)
To avoid breaking binary compatibility, they are passed as args. */
regs->gprs[4] = current->thread.trap_no;
regs->gprs[5] = current->thread.prot_addr;
+
+ /* Place signal number on stack to allow backtrace from handler. */
+ if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
+ goto give_sigsegv;
return;
give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
}
static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
return;
give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
}
/*
*/
void
-handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
- struct pt_regs * regs)
+handle_signal32(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{
- struct k_sigaction *ka = ¤t->sighand->action[sig-1];
-
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame32(sig, ka, info, oldset, regs);
else
setup_frame32(sig, ka, oldset, regs);
- if (ka->sa.sa_flags & SA_ONESHOT)
- ka->sa.sa_handler = SIG_DFL;
-
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(¤t->sighand->siglock);
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);