summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/signal.c')
-rw-r--r--arch/sparc64/kernel/signal.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index efd6a64d1..f893e7f3a 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -42,6 +42,38 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
/* #define DEBUG_SIGNALS_TRACE 1 */
/* #define DEBUG_SIGNALS_MAPS 1 */
+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
+{
+ if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
+ return -EFAULT;
+ if (from->si_code < 0)
+ return __copy_to_user(to, from, sizeof(siginfo_t));
+ else {
+ int err;
+
+ /* If you change siginfo_t structure, please be sure
+ this code is fixed accordingly.
+ It should never copy any pad contained in the structure
+ to avoid security leaks, but must copy the generic
+ 3 ints plus the relevant union member. */
+ err = __put_user(*(long *)&from->si_signo, (long *)&to->si_signo);
+ err |= __put_user((short)from->si_code, &to->si_code);
+ switch (from->si_code >> 16) {
+ case __SI_CHLD >> 16:
+ err |= __put_user(from->si_utime, &to->si_utime);
+ err |= __put_user(from->si_stime, &to->si_stime);
+ case __SI_FAULT >> 16:
+ case __SI_POLL >> 16:
+ err |= __put_user(from->si_trapno, &to->si_trapno);
+ default:
+ err |= __put_user(from->si_addr, &to->si_addr);
+ break;
+ /* case __SI_RT: This is not generated by the kernel as of now. */
+ }
+ return err;
+ }
+}
+
/* {set, get}context() needed for 64-bit SparcLinux userland. */
asmlinkage void sparc64_set_context(struct pt_regs *regs)
{
@@ -512,7 +544,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
sizeof(struct reg_window));
if (info)
- err |= copy_to_user(&sf->info, info, sizeof(siginfo_t));
+ err |= copy_siginfo_to_user(&sf->info, info);
else {
err |= __put_user(signo, &sf->info.si_signo);
err |= __put_user(SI_NOINFO, &sf->info.si_code);