]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-4.9/signal-ptrace-don-t-leak-unitialized-kernel-memory-with-ptrace_peek_siginfo.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.9 / signal-ptrace-don-t-leak-unitialized-kernel-memory-with-ptrace_peek_siginfo.patch
CommitLineData
96f81b03
GKH
1From f6e2aa91a46d2bc79fce9b93a988dbe7655c90c0 Mon Sep 17 00:00:00 2001
2From: "Eric W. Biederman" <ebiederm@xmission.com>
3Date: Tue, 28 May 2019 18:46:37 -0500
4Subject: signal/ptrace: Don't leak unitialized kernel memory with PTRACE_PEEK_SIGINFO
5
6From: Eric W. Biederman <ebiederm@xmission.com>
7
8commit f6e2aa91a46d2bc79fce9b93a988dbe7655c90c0 upstream.
9
10Recently syzbot in conjunction with KMSAN reported that
11ptrace_peek_siginfo can copy an uninitialized siginfo to userspace.
12Inspecting ptrace_peek_siginfo confirms this.
13
14The problem is that off when initialized from args.off can be
15initialized to a negaive value. At which point the "if (off >= 0)"
16test to see if off became negative fails because off started off
17negative.
18
19Prevent the core problem by adding a variable found that is only true
20if a siginfo is found and copied to a temporary in preparation for
21being copied to userspace.
22
23Prevent args.off from being truncated when being assigned to off by
24testing that off is <= the maximum possible value of off. Convert off
25to an unsigned long so that we should not have to truncate args.off,
26we have well defined overflow behavior so if we add another check we
27won't risk fighting undefined compiler behavior, and so that we have a
28type whose maximum value is easy to test for.
29
30Cc: Andrei Vagin <avagin@gmail.com>
31Cc: stable@vger.kernel.org
32Reported-by: syzbot+0d602a1b0d8c95bdf299@syzkaller.appspotmail.com
33Fixes: 84c751bd4aeb ("ptrace: add ability to retrieve signals without removing from a queue (v4)")
34Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
35Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
36
37---
38 kernel/ptrace.c | 9 +++++++--
39 1 file changed, 7 insertions(+), 2 deletions(-)
40
41--- a/kernel/ptrace.c
42+++ b/kernel/ptrace.c
43@@ -710,6 +710,10 @@ static int ptrace_peek_siginfo(struct ta
44 if (arg.nr < 0)
45 return -EINVAL;
46
47+ /* Ensure arg.off fits in an unsigned long */
48+ if (arg.off > ULONG_MAX)
49+ return 0;
50+
51 if (arg.flags & PTRACE_PEEKSIGINFO_SHARED)
52 pending = &child->signal->shared_pending;
53 else
54@@ -717,7 +721,8 @@ static int ptrace_peek_siginfo(struct ta
55
56 for (i = 0; i < arg.nr; ) {
57 siginfo_t info;
58- s32 off = arg.off + i;
59+ unsigned long off = arg.off + i;
60+ bool found = false;
61
62 spin_lock_irq(&child->sighand->siglock);
63 list_for_each_entry(q, &pending->list, list) {
64@@ -728,7 +733,7 @@ static int ptrace_peek_siginfo(struct ta
65 }
66 spin_unlock_irq(&child->sighand->siglock);
67
68- if (off >= 0) /* beyond the end of the list */
69+ if (!found) /* beyond the end of the list */
70 break;
71
72 #ifdef CONFIG_COMPAT