diff options
Diffstat (limited to 'arch/parisc/kernel/signal32.c')
-rw-r--r-- | arch/parisc/kernel/signal32.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index a6b4231cafa..1c1a37f7305 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -1,6 +1,8 @@ /* Signal support for 32-bit kernel builds * * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org> + * Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org> + * * Code was mostly borrowed from kernel/signal.c. * See kernel/signal.c for additional Copyrights. * @@ -401,7 +403,7 @@ setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __ int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from) { - unsigned long tmp; + compat_uptr_t addr; int err; if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) @@ -424,8 +426,8 @@ copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from) err |= __get_user(to->si_uid, &from->si_uid); break; case __SI_FAULT >> 16: - err |= __get_user(tmp, &from->si_addr); - to->si_addr = (void __user *) tmp; + err |= __get_user(addr, &from->si_addr); + to->si_addr = compat_ptr(addr); break; case __SI_POLL >> 16: err |= __get_user(to->si_band, &from->si_band); @@ -445,7 +447,8 @@ copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from) int copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from) { - unsigned int addr; + compat_uptr_t addr; + compat_int_t val; int err; if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) @@ -474,8 +477,8 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from) err |= __put_user(from->si_uid, &to->si_uid); break; case __SI_FAULT >> 16: - /* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */ - err |= __put_user(from->_sifields._pad[0], &to->si_addr); + addr = ptr_to_compat(from->si_addr); + err |= __put_user(addr, &to->si_addr); break; case __SI_POLL >> 16: err |= __put_user(from->si_band, &to->si_band); @@ -484,17 +487,36 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from) case __SI_TIMER >> 16: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); - addr = (unsigned long) from->si_ptr; - err |= __put_user(addr, &to->si_ptr); + val = (compat_int_t)from->si_int; + err |= __put_user(val, &to->si_int); break; case __SI_RT >> 16: /* Not generated by the kernel as of now. */ case __SI_MESGQ >> 16: err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_pid, &to->si_pid); - addr = (unsigned long) from->si_ptr; - err |= __put_user(addr, &to->si_ptr); + val = (compat_int_t)from->si_int; + err |= __put_user(val, &to->si_int); break; } } return err; } + +asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig, + struct compat_siginfo __user *uinfo) +{ + siginfo_t info; + + if (copy_siginfo_from_user32(&info, uinfo)) + return -EFAULT; + + /* Not even root can pretend to send signals from the kernel. + Nor can they impersonate a kill(), which adds source info. */ + if (info.si_code >= 0) + return -EPERM; + info.si_signo = sig; + + /* POSIX.1b doesn't mention process groups. */ + return kill_proc_info(sig, &info, pid); +} + |