Commit 9d33a271 authored by Stephen Rothwell's avatar Stephen Rothwell Committed by Linus Torvalds

[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.
parent e784b458
......@@ -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. */
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);
/* First 32bits of unions are always present. */
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:
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 >> 16:
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);
err |= __put_user(from->si_status, &to->si_status);
default:
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;
/* case __SI_RT: This is not generated by the kernel as of now. */
}
return err;
}
}
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment