diff options
| author | Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | 2013-06-28 09:49:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-06-29 14:29:08 -0400 |
| commit | 706b23bde27a391f0974df2a8351661770fa2e07 (patch) | |
| tree | 2b8d6be33dda49dcfc9ed8a5a688db4e8f56ac4c | |
| parent | bd2931b5cff6a3bf39bfe15fae051fb8229c0029 (diff) | |
Fix: kernel/ptrace.c: ptrace_peek_siginfo() missing __put_user() validation
This __put_user() could be used by unprivileged processes to write into
kernel memory. The issue here is that even if copy_siginfo_to_user()
fails, the error code is not checked before __put_user() is executed.
Luckily, ptrace_peek_siginfo() has been added within the 3.10-rc cycle,
so it has not hit a stable release yet.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Cc: Andrey Vagin <avagin@openvz.org>
Cc: Roland McGrath <roland@redhat.com>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Dave Jones <davej@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Pedro Alves <palves@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | kernel/ptrace.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index aed981a3f69c..335a7ae697f5 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
| @@ -665,20 +665,22 @@ static int ptrace_peek_siginfo(struct task_struct *child, | |||
| 665 | if (unlikely(is_compat_task())) { | 665 | if (unlikely(is_compat_task())) { |
| 666 | compat_siginfo_t __user *uinfo = compat_ptr(data); | 666 | compat_siginfo_t __user *uinfo = compat_ptr(data); |
| 667 | 667 | ||
| 668 | ret = copy_siginfo_to_user32(uinfo, &info); | 668 | if (copy_siginfo_to_user32(uinfo, &info) || |
| 669 | ret |= __put_user(info.si_code, &uinfo->si_code); | 669 | __put_user(info.si_code, &uinfo->si_code)) { |
| 670 | ret = -EFAULT; | ||
| 671 | break; | ||
| 672 | } | ||
| 673 | |||
| 670 | } else | 674 | } else |
| 671 | #endif | 675 | #endif |
| 672 | { | 676 | { |
| 673 | siginfo_t __user *uinfo = (siginfo_t __user *) data; | 677 | siginfo_t __user *uinfo = (siginfo_t __user *) data; |
| 674 | 678 | ||
| 675 | ret = copy_siginfo_to_user(uinfo, &info); | 679 | if (copy_siginfo_to_user(uinfo, &info) || |
| 676 | ret |= __put_user(info.si_code, &uinfo->si_code); | 680 | __put_user(info.si_code, &uinfo->si_code)) { |
| 677 | } | 681 | ret = -EFAULT; |
| 678 | 682 | break; | |
| 679 | if (ret) { | 683 | } |
| 680 | ret = -EFAULT; | ||
| 681 | break; | ||
| 682 | } | 684 | } |
| 683 | 685 | ||
| 684 | data += sizeof(siginfo_t); | 686 | data += sizeof(siginfo_t); |
