Contents of /trunk/kernel26-magellan/patches-2.6.35-r3/0301-2.6.35-CVE-2010-3301.patch
Parent Directory | Revision Log
Revision 1136 -
(show annotations)
(download)
Sat Sep 18 11:01:49 2010 UTC (14 years ago) by niro
File size: 7714 byte(s)
Sat Sep 18 11:01:49 2010 UTC (14 years ago) by niro
File size: 7714 byte(s)
-2.6.35-magellan-r3; added patch to fix CVE-2010-3301
1 | From c41d68a513c71e35a14f66d71782d27a79a81ea6 Mon Sep 17 00:00:00 2001 |
2 | From: H. Peter Anvin <hpa@linux.intel.com> |
3 | Date: Tue, 7 Sep 2010 16:16:18 -0700 |
4 | Subject: [PATCH] compat: Make compat_alloc_user_space() incorporate the access_ok() |
5 | |
6 | compat_alloc_user_space() expects the caller to independently call |
7 | access_ok() to verify the returned area. A missing call could |
8 | introduce problems on some architectures. |
9 | |
10 | This patch incorporates the access_ok() check into |
11 | compat_alloc_user_space() and also adds a sanity check on the length. |
12 | The existing compat_alloc_user_space() implementations are renamed |
13 | arch_compat_alloc_user_space() and are used as part of the |
14 | implementation of the new global function. |
15 | |
16 | This patch assumes NULL will cause __get_user()/__put_user() to either |
17 | fail or access userspace on all architectures. This should be |
18 | followed by checking the return value of compat_access_user_space() |
19 | for NULL in the callers, at which time the access_ok() in the callers |
20 | can also be removed. |
21 | |
22 | Reported-by: Ben Hawkes <hawkes@sota.gen.nz> |
23 | Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> |
24 | Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> |
25 | Acked-by: Chris Metcalf <cmetcalf@tilera.com> |
26 | Acked-by: David S. Miller <davem@davemloft.net> |
27 | Acked-by: Ingo Molnar <mingo@elte.hu> |
28 | Acked-by: Thomas Gleixner <tglx@linutronix.de> |
29 | Acked-by: Tony Luck <tony.luck@intel.com> |
30 | Cc: Andrew Morton <akpm@linux-foundation.org> |
31 | Cc: Arnd Bergmann <arnd@arndb.de> |
32 | Cc: Fenghua Yu <fenghua.yu@intel.com> |
33 | Cc: H. Peter Anvin <hpa@zytor.com> |
34 | Cc: Heiko Carstens <heiko.carstens@de.ibm.com> |
35 | Cc: Helge Deller <deller@gmx.de> |
36 | Cc: James Bottomley <jejb@parisc-linux.org> |
37 | Cc: Kyle McMartin <kyle@mcmartin.ca> |
38 | Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> |
39 | Cc: Paul Mackerras <paulus@samba.org> |
40 | Cc: Ralf Baechle <ralf@linux-mips.org> |
41 | Cc: <stable@kernel.org> |
42 | --- |
43 | arch/ia64/include/asm/compat.h | 2 +- |
44 | arch/mips/include/asm/compat.h | 2 +- |
45 | arch/parisc/include/asm/compat.h | 2 +- |
46 | arch/powerpc/include/asm/compat.h | 2 +- |
47 | arch/s390/include/asm/compat.h | 2 +- |
48 | arch/sparc/include/asm/compat.h | 2 +- |
49 | arch/tile/include/asm/compat.h | 2 +- |
50 | arch/x86/include/asm/compat.h | 2 +- |
51 | include/linux/compat.h | 3 +++ |
52 | kernel/compat.c | 21 +++++++++++++++++++++ |
53 | 10 files changed, 32 insertions(+), 8 deletions(-) |
54 | |
55 | diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h |
56 | index f90edc8..9301a28 100644 |
57 | --- a/arch/ia64/include/asm/compat.h |
58 | +++ b/arch/ia64/include/asm/compat.h |
59 | @@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr) |
60 | } |
61 | |
62 | static __inline__ void __user * |
63 | -compat_alloc_user_space (long len) |
64 | +arch_compat_alloc_user_space (long len) |
65 | { |
66 | struct pt_regs *regs = task_pt_regs(current); |
67 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); |
68 | diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h |
69 | index 613f691..dbc5106 100644 |
70 | --- a/arch/mips/include/asm/compat.h |
71 | +++ b/arch/mips/include/asm/compat.h |
72 | @@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) |
73 | return (u32)(unsigned long)uptr; |
74 | } |
75 | |
76 | -static inline void __user *compat_alloc_user_space(long len) |
77 | +static inline void __user *arch_compat_alloc_user_space(long len) |
78 | { |
79 | struct pt_regs *regs = (struct pt_regs *) |
80 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; |
81 | diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h |
82 | index 02b77ba..efa0b60 100644 |
83 | --- a/arch/parisc/include/asm/compat.h |
84 | +++ b/arch/parisc/include/asm/compat.h |
85 | @@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) |
86 | return (u32)(unsigned long)uptr; |
87 | } |
88 | |
89 | -static __inline__ void __user *compat_alloc_user_space(long len) |
90 | +static __inline__ void __user *arch_compat_alloc_user_space(long len) |
91 | { |
92 | struct pt_regs *regs = ¤t->thread.regs; |
93 | return (void __user *)regs->gr[30]; |
94 | diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h |
95 | index 396d21a..a11d4ea 100644 |
96 | --- a/arch/powerpc/include/asm/compat.h |
97 | +++ b/arch/powerpc/include/asm/compat.h |
98 | @@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) |
99 | return (u32)(unsigned long)uptr; |
100 | } |
101 | |
102 | -static inline void __user *compat_alloc_user_space(long len) |
103 | +static inline void __user *arch_compat_alloc_user_space(long len) |
104 | { |
105 | struct pt_regs *regs = current->thread.regs; |
106 | unsigned long usp = regs->gpr[1]; |
107 | diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h |
108 | index 104f200..a875c2f 100644 |
109 | --- a/arch/s390/include/asm/compat.h |
110 | +++ b/arch/s390/include/asm/compat.h |
111 | @@ -181,7 +181,7 @@ static inline int is_compat_task(void) |
112 | |
113 | #endif |
114 | |
115 | -static inline void __user *compat_alloc_user_space(long len) |
116 | +static inline void __user *arch_compat_alloc_user_space(long len) |
117 | { |
118 | unsigned long stack; |
119 | |
120 | diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h |
121 | index 5016f76..6f57325 100644 |
122 | --- a/arch/sparc/include/asm/compat.h |
123 | +++ b/arch/sparc/include/asm/compat.h |
124 | @@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) |
125 | return (u32)(unsigned long)uptr; |
126 | } |
127 | |
128 | -static inline void __user *compat_alloc_user_space(long len) |
129 | +static inline void __user *arch_compat_alloc_user_space(long len) |
130 | { |
131 | struct pt_regs *regs = current_thread_info()->kregs; |
132 | unsigned long usp = regs->u_regs[UREG_I6]; |
133 | diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h |
134 | index 5a34da6..345d81c 100644 |
135 | --- a/arch/tile/include/asm/compat.h |
136 | +++ b/arch/tile/include/asm/compat.h |
137 | @@ -195,7 +195,7 @@ static inline unsigned long ptr_to_compat_reg(void __user *uptr) |
138 | return (long)(int)(long __force)uptr; |
139 | } |
140 | |
141 | -static inline void __user *compat_alloc_user_space(long len) |
142 | +static inline void __user *arch_compat_alloc_user_space(long len) |
143 | { |
144 | struct pt_regs *regs = task_pt_regs(current); |
145 | return (void __user *)regs->sp - len; |
146 | diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h |
147 | index 306160e..1d9cd27 100644 |
148 | --- a/arch/x86/include/asm/compat.h |
149 | +++ b/arch/x86/include/asm/compat.h |
150 | @@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) |
151 | return (u32)(unsigned long)uptr; |
152 | } |
153 | |
154 | -static inline void __user *compat_alloc_user_space(long len) |
155 | +static inline void __user *arch_compat_alloc_user_space(long len) |
156 | { |
157 | struct pt_regs *regs = task_pt_regs(current); |
158 | return (void __user *)regs->sp - len; |
159 | diff --git a/include/linux/compat.h b/include/linux/compat.h |
160 | index 9ddc878..5778b55 100644 |
161 | --- a/include/linux/compat.h |
162 | +++ b/include/linux/compat.h |
163 | @@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type, |
164 | const struct compat_iovec __user *uvector, unsigned long nr_segs, |
165 | unsigned long fast_segs, struct iovec *fast_pointer, |
166 | struct iovec **ret_pointer); |
167 | + |
168 | +extern void __user *compat_alloc_user_space(unsigned long len); |
169 | + |
170 | #endif /* CONFIG_COMPAT */ |
171 | #endif /* _LINUX_COMPAT_H */ |
172 | diff --git a/kernel/compat.c b/kernel/compat.c |
173 | index e167efc..c9e2ec0 100644 |
174 | --- a/kernel/compat.c |
175 | +++ b/kernel/compat.c |
176 | @@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) |
177 | |
178 | return 0; |
179 | } |
180 | + |
181 | +/* |
182 | + * Allocate user-space memory for the duration of a single system call, |
183 | + * in order to marshall parameters inside a compat thunk. |
184 | + */ |
185 | +void __user *compat_alloc_user_space(unsigned long len) |
186 | +{ |
187 | + void __user *ptr; |
188 | + |
189 | + /* If len would occupy more than half of the entire compat space... */ |
190 | + if (unlikely(len > (((compat_uptr_t)~0) >> 1))) |
191 | + return NULL; |
192 | + |
193 | + ptr = arch_compat_alloc_user_space(len); |
194 | + |
195 | + if (unlikely(!access_ok(VERIFY_WRITE, ptr, len))) |
196 | + return NULL; |
197 | + |
198 | + return ptr; |
199 | +} |
200 | +EXPORT_SYMBOL_GPL(compat_alloc_user_space); |
201 | -- |
202 | 1.7.2.3 |
203 |