Annotation of /trunk/kernel26-magellan/patches-2.6.35-r3/0301-2.6.35-CVE-2010-3301.patch
Parent Directory | Revision Log
Revision 1137 -
(hide annotations)
(download)
Mon Sep 20 07:44:10 2010 UTC (14 years ago) by niro
File size: 7138 byte(s)
Mon Sep 20 07:44:10 2010 UTC (14 years ago) by niro
File size: 7138 byte(s)
-fixed patch
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/x86/include/asm/compat.h | 2 +- | ||
50 | include/linux/compat.h | 3 +++ | ||
51 | kernel/compat.c | 21 +++++++++++++++++++++ | ||
52 | 10 files changed, 32 insertions(+), 8 deletions(-) | ||
53 | |||
54 | diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h | ||
55 | index f90edc8..9301a28 100644 | ||
56 | --- a/arch/ia64/include/asm/compat.h | ||
57 | +++ b/arch/ia64/include/asm/compat.h | ||
58 | @@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr) | ||
59 | } | ||
60 | |||
61 | static __inline__ void __user * | ||
62 | -compat_alloc_user_space (long len) | ||
63 | +arch_compat_alloc_user_space (long len) | ||
64 | { | ||
65 | struct pt_regs *regs = task_pt_regs(current); | ||
66 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); | ||
67 | diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h | ||
68 | index 613f691..dbc5106 100644 | ||
69 | --- a/arch/mips/include/asm/compat.h | ||
70 | +++ b/arch/mips/include/asm/compat.h | ||
71 | @@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | ||
72 | return (u32)(unsigned long)uptr; | ||
73 | } | ||
74 | |||
75 | -static inline void __user *compat_alloc_user_space(long len) | ||
76 | +static inline void __user *arch_compat_alloc_user_space(long len) | ||
77 | { | ||
78 | struct pt_regs *regs = (struct pt_regs *) | ||
79 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; | ||
80 | diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h | ||
81 | index 02b77ba..efa0b60 100644 | ||
82 | --- a/arch/parisc/include/asm/compat.h | ||
83 | +++ b/arch/parisc/include/asm/compat.h | ||
84 | @@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | ||
85 | return (u32)(unsigned long)uptr; | ||
86 | } | ||
87 | |||
88 | -static __inline__ void __user *compat_alloc_user_space(long len) | ||
89 | +static __inline__ void __user *arch_compat_alloc_user_space(long len) | ||
90 | { | ||
91 | struct pt_regs *regs = ¤t->thread.regs; | ||
92 | return (void __user *)regs->gr[30]; | ||
93 | diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h | ||
94 | index 396d21a..a11d4ea 100644 | ||
95 | --- a/arch/powerpc/include/asm/compat.h | ||
96 | +++ b/arch/powerpc/include/asm/compat.h | ||
97 | @@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | ||
98 | return (u32)(unsigned long)uptr; | ||
99 | } | ||
100 | |||
101 | -static inline void __user *compat_alloc_user_space(long len) | ||
102 | +static inline void __user *arch_compat_alloc_user_space(long len) | ||
103 | { | ||
104 | struct pt_regs *regs = current->thread.regs; | ||
105 | unsigned long usp = regs->gpr[1]; | ||
106 | diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h | ||
107 | index 104f200..a875c2f 100644 | ||
108 | --- a/arch/s390/include/asm/compat.h | ||
109 | +++ b/arch/s390/include/asm/compat.h | ||
110 | @@ -181,7 +181,7 @@ static inline int is_compat_task(void) | ||
111 | |||
112 | #endif | ||
113 | |||
114 | -static inline void __user *compat_alloc_user_space(long len) | ||
115 | +static inline void __user *arch_compat_alloc_user_space(long len) | ||
116 | { | ||
117 | unsigned long stack; | ||
118 | |||
119 | diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h | ||
120 | index 5016f76..6f57325 100644 | ||
121 | --- a/arch/sparc/include/asm/compat.h | ||
122 | +++ b/arch/sparc/include/asm/compat.h | ||
123 | @@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | ||
124 | return (u32)(unsigned long)uptr; | ||
125 | } | ||
126 | |||
127 | -static inline void __user *compat_alloc_user_space(long len) | ||
128 | +static inline void __user *arch_compat_alloc_user_space(long len) | ||
129 | { | ||
130 | struct pt_regs *regs = current_thread_info()->kregs; | ||
131 | unsigned long usp = regs->u_regs[UREG_I6]; | ||
132 | diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h | ||
133 | index 306160e..1d9cd27 100644 | ||
134 | --- a/arch/x86/include/asm/compat.h | ||
135 | +++ b/arch/x86/include/asm/compat.h | ||
136 | @@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | ||
137 | return (u32)(unsigned long)uptr; | ||
138 | } | ||
139 | |||
140 | -static inline void __user *compat_alloc_user_space(long len) | ||
141 | +static inline void __user *arch_compat_alloc_user_space(long len) | ||
142 | { | ||
143 | struct pt_regs *regs = task_pt_regs(current); | ||
144 | return (void __user *)regs->sp - len; | ||
145 | diff --git a/include/linux/compat.h b/include/linux/compat.h | ||
146 | index 9ddc878..5778b55 100644 | ||
147 | --- a/include/linux/compat.h | ||
148 | +++ b/include/linux/compat.h | ||
149 | @@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type, | ||
150 | const struct compat_iovec __user *uvector, unsigned long nr_segs, | ||
151 | unsigned long fast_segs, struct iovec *fast_pointer, | ||
152 | struct iovec **ret_pointer); | ||
153 | + | ||
154 | +extern void __user *compat_alloc_user_space(unsigned long len); | ||
155 | + | ||
156 | #endif /* CONFIG_COMPAT */ | ||
157 | #endif /* _LINUX_COMPAT_H */ | ||
158 | diff --git a/kernel/compat.c b/kernel/compat.c | ||
159 | index e167efc..c9e2ec0 100644 | ||
160 | --- a/kernel/compat.c | ||
161 | +++ b/kernel/compat.c | ||
162 | @@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | + | ||
167 | +/* | ||
168 | + * Allocate user-space memory for the duration of a single system call, | ||
169 | + * in order to marshall parameters inside a compat thunk. | ||
170 | + */ | ||
171 | +void __user *compat_alloc_user_space(unsigned long len) | ||
172 | +{ | ||
173 | + void __user *ptr; | ||
174 | + | ||
175 | + /* If len would occupy more than half of the entire compat space... */ | ||
176 | + if (unlikely(len > (((compat_uptr_t)~0) >> 1))) | ||
177 | + return NULL; | ||
178 | + | ||
179 | + ptr = arch_compat_alloc_user_space(len); | ||
180 | + | ||
181 | + if (unlikely(!access_ok(VERIFY_WRITE, ptr, len))) | ||
182 | + return NULL; | ||
183 | + | ||
184 | + return ptr; | ||
185 | +} | ||
186 | +EXPORT_SYMBOL_GPL(compat_alloc_user_space); | ||
187 | -- | ||
188 | 1.7.2.3 | ||
189 |