waitid(): switch copyout of siginfo to unsafe_put_user()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 14 May 2017 23:27:32 +0000 (19:27 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 21 May 2017 17:16:18 +0000 (13:16 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
kernel/exit.c

index 97db9ee03f901204188adafd15cd28dd7852e3ee..f3b8c3a87bc197a4b4a8a494e8021f079ceb40c9 100644 (file)
@@ -1625,15 +1625,18 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
        if (!infop)
                return err;
 
-       if (put_user(err ? 0 : SIGCHLD, &infop->si_signo) ||
-           put_user(0, &infop->si_errno) ||
-           put_user((short)info.cause, &infop->si_code) ||
-           put_user(info.pid, &infop->si_pid) ||
-           put_user(info.uid, &infop->si_uid) ||
-           put_user(info.status, &infop->si_status))
-               err = -EFAULT;
-
+       user_access_begin();
+       unsafe_put_user(err ? 0 : SIGCHLD, &infop->si_signo, Efault);
+       unsafe_put_user(0, &infop->si_errno, Efault);
+       unsafe_put_user((short)info.cause, &infop->si_code, Efault);
+       unsafe_put_user(info.pid, &infop->si_pid, Efault);
+       unsafe_put_user(info.uid, &infop->si_uid, Efault);
+       unsafe_put_user(info.status, &infop->si_status, Efault);
+       user_access_end();
        return err;
+Efault:
+       user_access_end();
+       return -EFAULT;
 }
 
 static long kernel_wait4(pid_t upid, int __user *stat_addr,
@@ -1736,13 +1739,20 @@ COMPAT_SYSCALL_DEFINE5(waitid,
                        return -EFAULT;
        }
 
-       if (put_user(err ? 0 : SIGCHLD, &infop->si_signo) ||
-           put_user(0, &infop->si_errno) ||
-           put_user((short)info.cause, &infop->si_code) ||
-           put_user(info.pid, &infop->si_pid) ||
-           put_user(info.uid, &infop->si_uid) ||
-           put_user(info.status, &infop->si_status))
-               err = -EFAULT;
+       if (!infop)
+               return err;
+
+       user_access_begin();
+       unsafe_put_user(err ? 0 : SIGCHLD, &infop->si_signo, Efault);
+       unsafe_put_user(0, &infop->si_errno, Efault);
+       unsafe_put_user((short)info.cause, &infop->si_code, Efault);
+       unsafe_put_user(info.pid, &infop->si_pid, Efault);
+       unsafe_put_user(info.uid, &infop->si_uid, Efault);
+       unsafe_put_user(info.status, &infop->si_status, Efault);
+       user_access_end();
        return err;
+Efault:
+       user_access_end();
+       return -EFAULT;
 }
 #endif