From 75907d4d7bc5d79b82d1453d9689efc588de1b43 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 25 Dec 2012 15:19:12 -0500 Subject: [PATCH] generic compat_sys_rt_sigqueueinfo() conditional on GENERIC_COMPAT_RT_SIGQUEUEINFO; by the end of that series it will become the same thing as COMPAT and conditional will die out. Signed-off-by: Al Viro --- arch/Kconfig | 3 +++ include/linux/compat.h | 4 ++++ kernel/signal.c | 47 +++++++++++++++++++++++++++++------------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 18c0383dcc42..c612b5ccfd84 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -365,6 +365,9 @@ config GENERIC_COMPAT_RT_SIGPROCMASK config GENERIC_COMPAT_RT_SIGPENDING bool +config GENERIC_COMPAT_RT_SIGQUEUEINFO + bool + # # ABI hall of shame # diff --git a/include/linux/compat.h b/include/linux/compat.h index 75548a43a1c5..bbee15ef3ae9 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -602,6 +602,10 @@ asmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, asmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset, compat_size_t sigsetsize); #endif +#ifdef CONFIG_GENERIC_COMPAT_RT_SIGQUEUEINFO +asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig, + struct compat_siginfo __user *uinfo); +#endif asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); diff --git a/kernel/signal.c b/kernel/signal.c index 3040c349b0e1..6cd3023cc66b 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2983,6 +2983,22 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int, sig) return do_tkill(0, pid, sig); } +static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info) +{ + /* Not even root can pretend to send signals from the kernel. + * Nor can they impersonate a kill()/tgkill(), which adds source info. + */ + if (info->si_code >= 0 || info->si_code == SI_TKILL) { + /* We used to allow any < 0 si_code */ + WARN_ON_ONCE(info->si_code < 0); + return -EPERM; + } + info->si_signo = sig; + + /* POSIX.1b doesn't mention process groups. */ + return kill_proc_info(sig, info, pid); +} + /** * sys_rt_sigqueueinfo - send signal information to a signal * @pid: the PID of the thread @@ -2993,24 +3009,27 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t __user *, uinfo) { siginfo_t info; - if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) return -EFAULT; - - /* Not even root can pretend to send signals from the kernel. - * Nor can they impersonate a kill()/tgkill(), which adds source info. - */ - if (info.si_code >= 0 || info.si_code == SI_TKILL) { - /* We used to allow any < 0 si_code */ - WARN_ON_ONCE(info.si_code < 0); - return -EPERM; - } - info.si_signo = sig; - - /* POSIX.1b doesn't mention process groups. */ - return kill_proc_info(sig, &info, pid); + return do_rt_sigqueueinfo(pid, sig, &info); } +#ifdef CONFIG_COMPAT +#ifdef CONFIG_GENERIC_COMPAT_RT_SIGQUEUEINFO +COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo, + compat_pid_t, pid, + int, sig, + struct compat_siginfo __user *, uinfo) +{ + siginfo_t info; + int ret = copy_siginfo_from_user32(&info, uinfo); + if (unlikely(ret)) + return ret; + return do_rt_sigqueueinfo(pid, sig, &info); +} +#endif +#endif + long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) { /* This is only valid for single tasks */