summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2002-06-17 20:59:18 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-06-17 20:59:18 -0700
commit9d33a2710c9604cb7102548d14517f393d0d30c3 (patch)
tree9d00b04748328553e5a8cd86f1066e8c6868baec
parente784b458b553ef0f2cb5cb036743ac72a0c91b28 (diff)
[PATCH] Make copy_siginfo_to_user mode explicit
This patch makes copy_siginfo_to_user excplicitly copy the correct union member. Previously we were getting the correct result but really by accident.
-rw-r--r--kernel/signal.c73
1 files changed, 47 insertions, 26 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index b61c19be4929..7fccdfbc965f 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1043,37 +1043,58 @@ sys_rt_sigpending(sigset_t *set, size_t sigsetsize)
int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
{
+ int err;
+
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(from->si_signo, &to->si_signo);
- err |= __put_user(from->si_errno, &to->si_errno);
- err |= __put_user((short)from->si_code, &to->si_code);
- /* First 32bits of unions are always present. */
+ return __copy_to_user(to, from, sizeof(siginfo_t))
+ ? -EFAULT : 0;
+ /*
+ * 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(from->si_signo, &to->si_signo);
+ err |= __put_user(from->si_errno, &to->si_errno);
+ err |= __put_user((short)from->si_code, &to->si_code);
+ switch (from->si_code & __SI_MASK) {
+ case __SI_KILL:
err |= __put_user(from->si_pid, &to->si_pid);
- switch (from->si_code >> 16) {
- case __SI_FAULT >> 16:
- break;
- case __SI_CHLD >> 16:
- err |= __put_user(from->si_utime, &to->si_utime);
- err |= __put_user(from->si_stime, &to->si_stime);
- err |= __put_user(from->si_status, &to->si_status);
- default:
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- /* case __SI_RT: This is not generated by the kernel as of now. */
- }
- return err;
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
+ case __SI_TIMER:
+ err |= __put_user(from->si_timer1, &to->si_timer1);
+ err |= __put_user(from->si_timer2, &to->si_timer2);
+ break;
+ case __SI_POLL:
+ err |= __put_user(from->si_band, &to->si_band);
+ err |= __put_user(from->si_fd, &to->si_fd);
+ break;
+ case __SI_FAULT:
+ err |= __put_user(from->si_addr, &to->si_addr);
+ break;
+ case __SI_CHLD:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_status, &to->si_status);
+ err |= __put_user(from->si_utime, &to->si_utime);
+ err |= __put_user(from->si_stime, &to->si_stime);
+ break;
+ case __SI_RT: /* This is not generated by the kernel as of now. */
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_int, &to->si_int);
+ err |= __put_user(from->si_ptr, &to->si_ptr);
+ break;
+ default: /* this is just in case for now ... */
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
}
+ return err;
}
#endif