]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - pending-4.9/signal-ptrace-don-t-leak-unitialized-kernel-memory-with-ptrace_peek_siginfo.patch
move existing queues out of the way for the moment...
[thirdparty/kernel/stable-queue.git] / pending-4.9 / signal-ptrace-don-t-leak-unitialized-kernel-memory-with-ptrace_peek_siginfo.patch
1 From 39b103390f376649e14abf4ea559c223085fcd81 Mon Sep 17 00:00:00 2001
2 From: "Eric W. Biederman" <ebiederm@xmission.com>
3 Date: Tue, 28 May 2019 18:46:37 -0500
4 Subject: [PATCH] signal/ptrace: Don't leak unitialized kernel memory with
5 PTRACE_PEEK_SIGINFO
6
7 [ Upstream commit f6e2aa91a46d2bc79fce9b93a988dbe7655c90c0 ]
8
9 Recently syzbot in conjunction with KMSAN reported that
10 ptrace_peek_siginfo can copy an uninitialized siginfo to userspace.
11 Inspecting ptrace_peek_siginfo confirms this.
12
13 The problem is that off when initialized from args.off can be
14 initialized to a negaive value. At which point the "if (off >= 0)"
15 test to see if off became negative fails because off started off
16 negative.
17
18 Prevent the core problem by adding a variable found that is only true
19 if a siginfo is found and copied to a temporary in preparation for
20 being copied to userspace.
21
22 Prevent args.off from being truncated when being assigned to off by
23 testing that off is <= the maximum possible value of off. Convert off
24 to an unsigned long so that we should not have to truncate args.off,
25 we have well defined overflow behavior so if we add another check we
26 won't risk fighting undefined compiler behavior, and so that we have a
27 type whose maximum value is easy to test for.
28
29 Cc: Andrei Vagin <avagin@gmail.com>
30 Cc: stable@vger.kernel.org
31 Reported-by: syzbot+0d602a1b0d8c95bdf299@syzkaller.appspotmail.com
32 Fixes: 84c751bd4aeb ("ptrace: add ability to retrieve signals without removing from a queue (v4)")
33 Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
34 Signed-off-by: Sasha Levin <sashal@kernel.org>
35 ---
36 kernel/ptrace.c | 10 ++++++++--
37 1 file changed, 8 insertions(+), 2 deletions(-)
38
39 diff --git a/kernel/ptrace.c b/kernel/ptrace.c
40 index efba851ee018..df06d2fcbb92 100644
41 --- a/kernel/ptrace.c
42 +++ b/kernel/ptrace.c
43 @@ -710,6 +710,10 @@ static int ptrace_peek_siginfo(struct task_struct *child,
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,18 +721,20 @@ static int ptrace_peek_siginfo(struct task_struct *child,
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 if (!off--) {
65 + found = true;
66 copy_siginfo(&info, &q->info);
67 break;
68 }
69 }
70 spin_unlock_irq(&child->sighand->siglock);
71
72 - if (off >= 0) /* beyond the end of the list */
73 + if (!found) /* beyond the end of the list */
74 break;
75
76 #ifdef CONFIG_COMPAT
77 --
78 2.20.1
79