signal: fix information leak in copy_siginfo_to_user
This function may copy the si_addr_lsb, si_lower and si_upper fields to user mode when they haven't been initialized, which can leak kernel stack data to user mode. Just checking the value of si_code is insufficient because the same si_code value is shared between multiple signals. This is solved by checking the value of si_signo in addition to si_code. Signed-off-by: Amanieu d'Antras <amanieu@gmail.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
3c00cb5e68
commit
26135022f8
2 changed files with 8 additions and 4 deletions
|
@ -168,7 +168,8 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
|||
* Other callers might not initialize the si_lsb field,
|
||||
* so check explicitely for the right codes here.
|
||||
*/
|
||||
if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)
|
||||
if (from->si_signo == SIGBUS &&
|
||||
(from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
|
||||
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
|
||||
#endif
|
||||
break;
|
||||
|
|
|
@ -2748,12 +2748,15 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
|
|||
* Other callers might not initialize the si_lsb field,
|
||||
* so check explicitly for the right codes here.
|
||||
*/
|
||||
if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)
|
||||
if (from->si_signo == SIGBUS &&
|
||||
(from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
|
||||
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
|
||||
#endif
|
||||
#ifdef SEGV_BNDERR
|
||||
err |= __put_user(from->si_lower, &to->si_lower);
|
||||
err |= __put_user(from->si_upper, &to->si_upper);
|
||||
if (from->si_signo == SIGSEGV && from->si_code == SEGV_BNDERR) {
|
||||
err |= __put_user(from->si_lower, &to->si_lower);
|
||||
err |= __put_user(from->si_upper, &to->si_upper);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case __SI_CHLD:
|
||||
|
|
Loading…
Reference in a new issue