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) ...@@ -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 copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
{ {
int err;
if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
return -EFAULT; return -EFAULT;
if (from->si_code < 0) if (from->si_code < 0)
return __copy_to_user(to, from, sizeof(siginfo_t)); return __copy_to_user(to, from, sizeof(siginfo_t))
else { ? -EFAULT : 0;
int err; /*
* If you change siginfo_t structure, please be sure
/* If you change siginfo_t structure, please be sure * this code is fixed accordingly.
this code is fixed accordingly. * It should never copy any pad contained in the structure
It should never copy any pad contained in the structure * to avoid security leaks, but must copy the generic
to avoid security leaks, but must copy the generic * 3 ints plus the relevant union member.
3 ints plus the relevant union member. */ */
err = __put_user(from->si_signo, &to->si_signo); err = __put_user(from->si_signo, &to->si_signo);
err |= __put_user(from->si_errno, &to->si_errno); err |= __put_user(from->si_errno, &to->si_errno);
err |= __put_user((short)from->si_code, &to->si_code); 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); err |= __put_user(from->si_pid, &to->si_pid);
switch (from->si_code >> 16) { err |= __put_user(from->si_uid, &to->si_uid);
case __SI_FAULT >> 16: 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; 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_utime, &to->si_utime);
err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_stime, &to->si_stime);
err |= __put_user(from->si_status, &to->si_status); break;
default: 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); err |= __put_user(from->si_uid, &to->si_uid);
break; break;
/* case __SI_RT: This is not generated by the kernel as of now. */
} }
return err; return err;
}
} }
#endif #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