]>
Commit | Line | Data |
---|---|---|
ef4bba65 GKH |
1 | From 3c00cb5e68dc719f2fc73a33b1b230aadfcb1309 Mon Sep 17 00:00:00 2001 |
2 | From: Amanieu d'Antras <amanieu@gmail.com> | |
3 | Date: Thu, 6 Aug 2015 15:46:26 -0700 | |
4 | Subject: signal: fix information leak in copy_siginfo_from_user32 | |
5 | ||
6 | From: Amanieu d'Antras <amanieu@gmail.com> | |
7 | ||
8 | commit 3c00cb5e68dc719f2fc73a33b1b230aadfcb1309 upstream. | |
9 | ||
10 | This function can leak kernel stack data when the user siginfo_t has a | |
11 | positive si_code value. The top 16 bits of si_code descibe which fields | |
12 | in the siginfo_t union are active, but they are treated inconsistently | |
13 | between copy_siginfo_from_user32, copy_siginfo_to_user32 and | |
14 | copy_siginfo_to_user. | |
15 | ||
16 | copy_siginfo_from_user32 is called from rt_sigqueueinfo and | |
17 | rt_tgsigqueueinfo in which the user has full control overthe top 16 bits | |
18 | of si_code. | |
19 | ||
20 | This fixes the following information leaks: | |
21 | x86: 8 bytes leaked when sending a signal from a 32-bit process to | |
22 | itself. This leak grows to 16 bytes if the process uses x32. | |
23 | (si_code = __SI_CHLD) | |
24 | x86: 100 bytes leaked when sending a signal from a 32-bit process to | |
25 | a 64-bit process. (si_code = -1) | |
26 | sparc: 4 bytes leaked when sending a signal from a 32-bit process to a | |
27 | 64-bit process. (si_code = any) | |
28 | ||
29 | parsic and s390 have similar bugs, but they are not vulnerable because | |
30 | rt_[tg]sigqueueinfo have checks that prevent sending a positive si_code | |
31 | to a different process. These bugs are also fixed for consistency. | |
32 | ||
33 | Signed-off-by: Amanieu d'Antras <amanieu@gmail.com> | |
34 | Cc: Oleg Nesterov <oleg@redhat.com> | |
35 | Cc: Ingo Molnar <mingo@kernel.org> | |
36 | Cc: Russell King <rmk@arm.linux.org.uk> | |
37 | Cc: Ralf Baechle <ralf@linux-mips.org> | |
38 | Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> | |
39 | Cc: Chris Metcalf <cmetcalf@ezchip.com> | |
40 | Cc: Paul Mackerras <paulus@samba.org> | |
41 | Cc: Michael Ellerman <mpe@ellerman.id.au> | |
42 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
43 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
44 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
45 | ||
46 | --- | |
47 | arch/arm64/kernel/signal32.c | 2 -- | |
48 | arch/mips/kernel/signal32.c | 2 -- | |
49 | arch/powerpc/kernel/signal_32.c | 2 -- | |
50 | kernel/signal.c | 4 ++-- | |
51 | 4 files changed, 2 insertions(+), 8 deletions(-) | |
52 | ||
53 | --- a/arch/arm64/kernel/signal32.c | |
54 | +++ b/arch/arm64/kernel/signal32.c | |
55 | @@ -221,8 +221,6 @@ int copy_siginfo_to_user32(compat_siginf | |
56 | ||
57 | int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | |
58 | { | |
59 | - memset(to, 0, sizeof *to); | |
60 | - | |
61 | if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) || | |
62 | copy_from_user(to->_sifields._pad, | |
63 | from->_sifields._pad, SI_PAD_SIZE)) | |
64 | --- a/arch/mips/kernel/signal32.c | |
65 | +++ b/arch/mips/kernel/signal32.c | |
66 | @@ -368,8 +368,6 @@ int copy_siginfo_to_user32(compat_siginf | |
67 | ||
68 | int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | |
69 | { | |
70 | - memset(to, 0, sizeof *to); | |
71 | - | |
72 | if (copy_from_user(to, from, 3*sizeof(int)) || | |
73 | copy_from_user(to->_sifields._pad, | |
74 | from->_sifields._pad, SI_PAD_SIZE32)) | |
75 | --- a/arch/powerpc/kernel/signal_32.c | |
76 | +++ b/arch/powerpc/kernel/signal_32.c | |
77 | @@ -949,8 +949,6 @@ int copy_siginfo_to_user32(struct compat | |
78 | ||
79 | int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) | |
80 | { | |
81 | - memset(to, 0, sizeof *to); | |
82 | - | |
83 | if (copy_from_user(to, from, 3*sizeof(int)) || | |
84 | copy_from_user(to->_sifields._pad, | |
85 | from->_sifields._pad, SI_PAD_SIZE32)) | |
86 | --- a/kernel/signal.c | |
87 | +++ b/kernel/signal.c | |
88 | @@ -3036,7 +3036,7 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo, | |
89 | int, sig, | |
90 | struct compat_siginfo __user *, uinfo) | |
91 | { | |
92 | - siginfo_t info; | |
93 | + siginfo_t info = {}; | |
94 | int ret = copy_siginfo_from_user32(&info, uinfo); | |
95 | if (unlikely(ret)) | |
96 | return ret; | |
97 | @@ -3082,7 +3082,7 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo | |
98 | int, sig, | |
99 | struct compat_siginfo __user *, uinfo) | |
100 | { | |
101 | - siginfo_t info; | |
102 | + siginfo_t info = {}; | |
103 | ||
104 | if (copy_siginfo_from_user32(&info, uinfo)) | |
105 | return -EFAULT; |