generic compat_sys_rt_sigqueueinfo()
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 25 Dec 2012 20:19:12 +0000 (15:19 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 3 Feb 2013 20:09:19 +0000 (15:09 -0500)
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 <viro@zeniv.linux.org.uk>
arch/Kconfig
include/linux/compat.h
kernel/signal.c

index 18c0383..c612b5c 100644 (file)
@@ -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
 #
index 75548a4..bbee15e 100644 (file)
@@ -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);
index 3040c34..6cd3023 100644 (file)
@@ -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,23 +3009,26 @@ 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;
+       return do_rt_sigqueueinfo(pid, sig, &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);
+#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)
 {