__u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
struct sigcontext32 sc;
_sigregs32 sregs;
+ int signo;
__u8 retcode[S390_SYSCALL_SIZE];
} sigframe32;
asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
-int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
+int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
{
int err;
return err;
}
+int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from)
+{
+ int err;
+ u32 tmp;
+
+ if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32)))
+ 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 (from->si_code < 0)
+ err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+ else {
+ switch (from->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:
+ case __SI_TIMER >> 16:
+ err |= __get_user(to->si_band, &from->si_band);
+ err |= __get_user(to->si_fd, &from->si_fd);
+ break;
+ default:
+ break;
+ }
+ }
+ return err;
+}
+
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
}
asmlinkage int
-sys32_rt_sigsuspend(struct pt_regs * regs,compat_sigset_t *unewset, size_t sigsetsize)
+sys32_rt_sigsuspend(struct pt_regs * regs, compat_sigset_t __user *unewset,
+ size_t sigsetsize)
{
sigset_t saveset, newset;
compat_sigset_t set32;
if (do_signal(regs, &saveset))
return -EINTR;
}
-}
+}
asmlinkage long
-sys32_sigaction(int sig, const struct old_sigaction32 *act,
- struct old_sigaction32 *oact)
+sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
+ struct old_sigaction32 __user *oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
int
do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact);
-asmlinkage long
-sys32_rt_sigaction(int sig, const struct sigaction32 *act,
- struct sigaction32 *oact, size_t sigsetsize)
+asmlinkage long
+sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
+ struct sigaction32 __user *oact, size_t sigsetsize)
{
struct k_sigaction new_ka, old_ka;
int ret;
}
asmlinkage long
-sys32_sigaltstack(const stack_t32 *uss, stack_t32 *uoss, struct pt_regs *regs)
+sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
+ struct pt_regs *regs)
{
stack_t kss, koss;
int ret, err = 0;
}
set_fs (KERNEL_DS);
- ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, regs->gprs[15]);
+ ret = do_sigaltstack((stack_t __user *) (uss ? &kss : NULL),
+ (stack_t __user *) (uoss ? &koss : NULL),
+ regs->gprs[15]);
set_fs (old_fs);
if (!ret && uoss) {
return ret;
}
-static int save_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
+static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
{
_s390_regs_common32 regs32;
int err, i;
sizeof(_s390_fp_regs32));
}
-static int restore_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
+static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
{
_s390_regs_common32 regs32;
int err, i;
asmlinkage long sys32_sigreturn(struct pt_regs *regs)
{
- sigframe32 *frame = (sigframe32 *)regs->gprs[15];
+ sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
sigset_t set;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
badframe:
force_sig(SIGSEGV, current);
return 0;
-}
+}
asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
{
- rt_sigframe32 *frame = (rt_sigframe32 *)regs->gprs[15];
+ rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
sigset_t set;
stack_t st;
__u32 ss_sp;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
- set_fs (KERNEL_DS);
- do_sigaltstack(&st, NULL, regs->gprs[15]);
+ set_fs (KERNEL_DS);
+ do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]);
set_fs (old_fs);
return regs->gprs[2];
/*
* Determine which stack to use..
*/
-static inline void *
+static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
{
unsigned long sp;
sp = (unsigned long) ka->sa.sa_restorer;
}
- return (void *)((sp - frame_size) & -8ul);
+ return (void __user *)((sp - frame_size) & -8ul);
}
static inline int map_signal(int sig)
static void setup_frame32(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs * regs)
{
- sigframe32 *frame = get_sigframe(ka, regs, sizeof(sigframe32));
+ sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
goto give_sigsegv;
} else {
regs->gprs[14] = (__u64) frame->retcode;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
- (u16 *)(frame->retcode)))
+ (u16 __user *)(frame->retcode)))
goto give_sigsegv;
}
/* Set up backchain. */
- if (__put_user(regs->gprs[15], (unsigned int *) frame))
+ if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
goto give_sigsegv;
/* Set up registers for signal handler */
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:
sigset_t *set, struct pt_regs * regs)
{
int err = 0;
- rt_sigframe32 *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
+ rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
goto give_sigsegv;
} else {
regs->gprs[14] = (__u64) frame->retcode;
err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
- (u16 *)(frame->retcode));
+ (u16 __user *)(frame->retcode));
}
/* Set up backchain. */
- if (__put_user(regs->gprs[15], (unsigned int *) frame))
+ if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
goto give_sigsegv;
/* Set up registers for signal handler */