Annotation of /trunk/kernel26-magellan/patches-2.6.35-r3/0301-2.6.35-CVE-2010-3301.patch
Parent Directory | Revision Log
Revision 1136 -
(hide annotations)
(download)
Sat Sep 18 11:01:49 2010 UTC (13 years, 8 months ago) by niro
File size: 7714 byte(s)
Sat Sep 18 11:01:49 2010 UTC (13 years, 8 months ago) by niro
File size: 7714 byte(s)
-2.6.35-magellan-r3; added patch to fix CVE-2010-3301
1 | niro | 1136 | 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 |