diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2010-09-07 19:16:18 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2010-09-14 19:08:45 -0400 |
commit | c41d68a513c71e35a14f66d71782d27a79a81ea6 (patch) | |
tree | 2729377678b4f0fa516404eec6c3a87a4fd7c823 /arch | |
parent | bfa88ea7ee9e6b4fd673e45a8cc0a8e0b7ef4761 (diff) |
compat: Make compat_alloc_user_space() incorporate the access_ok()
compat_alloc_user_space() expects the caller to independently call
access_ok() to verify the returned area. A missing call could
introduce problems on some architectures.
This patch incorporates the access_ok() check into
compat_alloc_user_space() and also adds a sanity check on the length.
The existing compat_alloc_user_space() implementations are renamed
arch_compat_alloc_user_space() and are used as part of the
implementation of the new global function.
This patch assumes NULL will cause __get_user()/__put_user() to either
fail or access userspace on all architectures. This should be
followed by checking the return value of compat_access_user_space()
for NULL in the callers, at which time the access_ok() in the callers
can also be removed.
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Chris Metcalf <cmetcalf@tilera.com>
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: Ingo Molnar <mingo@elte.hu>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Tony Luck <tony.luck@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Helge Deller <deller@gmx.de>
Cc: James Bottomley <jejb@parisc-linux.org>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: <stable@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/include/asm/compat.h | 2 | ||||
-rw-r--r-- | arch/mips/include/asm/compat.h | 2 | ||||
-rw-r--r-- | arch/parisc/include/asm/compat.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/compat.h | 2 | ||||
-rw-r--r-- | arch/s390/include/asm/compat.h | 2 | ||||
-rw-r--r-- | arch/sparc/include/asm/compat.h | 2 | ||||
-rw-r--r-- | arch/tile/include/asm/compat.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/compat.h | 2 |
8 files changed, 8 insertions, 8 deletions
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h index f90edc85b50..9301a282161 100644 --- a/arch/ia64/include/asm/compat.h +++ b/arch/ia64/include/asm/compat.h | |||
@@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | static __inline__ void __user * | 201 | static __inline__ void __user * |
202 | compat_alloc_user_space (long len) | 202 | arch_compat_alloc_user_space (long len) |
203 | { | 203 | { |
204 | struct pt_regs *regs = task_pt_regs(current); | 204 | struct pt_regs *regs = task_pt_regs(current); |
205 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); | 205 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); |
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 613f6912dfc..dbc51065df5 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h | |||
@@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
145 | return (u32)(unsigned long)uptr; | 145 | return (u32)(unsigned long)uptr; |
146 | } | 146 | } |
147 | 147 | ||
148 | static inline void __user *compat_alloc_user_space(long len) | 148 | static inline void __user *arch_compat_alloc_user_space(long len) |
149 | { | 149 | { |
150 | struct pt_regs *regs = (struct pt_regs *) | 150 | struct pt_regs *regs = (struct pt_regs *) |
151 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; | 151 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; |
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 02b77baa5da..efa0b60c63f 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h | |||
@@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
147 | return (u32)(unsigned long)uptr; | 147 | return (u32)(unsigned long)uptr; |
148 | } | 148 | } |
149 | 149 | ||
150 | static __inline__ void __user *compat_alloc_user_space(long len) | 150 | static __inline__ void __user *arch_compat_alloc_user_space(long len) |
151 | { | 151 | { |
152 | struct pt_regs *regs = ¤t->thread.regs; | 152 | struct pt_regs *regs = ¤t->thread.regs; |
153 | return (void __user *)regs->gr[30]; | 153 | return (void __user *)regs->gr[30]; |
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 396d21a8005..a11d4eac4f9 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h | |||
@@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
134 | return (u32)(unsigned long)uptr; | 134 | return (u32)(unsigned long)uptr; |
135 | } | 135 | } |
136 | 136 | ||
137 | static inline void __user *compat_alloc_user_space(long len) | 137 | static inline void __user *arch_compat_alloc_user_space(long len) |
138 | { | 138 | { |
139 | struct pt_regs *regs = current->thread.regs; | 139 | struct pt_regs *regs = current->thread.regs; |
140 | unsigned long usp = regs->gpr[1]; | 140 | unsigned long usp = regs->gpr[1]; |
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 104f2007f09..a875c2f542e 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h | |||
@@ -181,7 +181,7 @@ static inline int is_compat_task(void) | |||
181 | 181 | ||
182 | #endif | 182 | #endif |
183 | 183 | ||
184 | static inline void __user *compat_alloc_user_space(long len) | 184 | static inline void __user *arch_compat_alloc_user_space(long len) |
185 | { | 185 | { |
186 | unsigned long stack; | 186 | unsigned long stack; |
187 | 187 | ||
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 5016f76ea98..6f57325bb88 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h | |||
@@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
167 | return (u32)(unsigned long)uptr; | 167 | return (u32)(unsigned long)uptr; |
168 | } | 168 | } |
169 | 169 | ||
170 | static inline void __user *compat_alloc_user_space(long len) | 170 | static inline void __user *arch_compat_alloc_user_space(long len) |
171 | { | 171 | { |
172 | struct pt_regs *regs = current_thread_info()->kregs; | 172 | struct pt_regs *regs = current_thread_info()->kregs; |
173 | unsigned long usp = regs->u_regs[UREG_I6]; | 173 | unsigned long usp = regs->u_regs[UREG_I6]; |
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 5a34da6cdd7..345d81ce44b 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h | |||
@@ -195,7 +195,7 @@ static inline unsigned long ptr_to_compat_reg(void __user *uptr) | |||
195 | return (long)(int)(long __force)uptr; | 195 | return (long)(int)(long __force)uptr; |
196 | } | 196 | } |
197 | 197 | ||
198 | static inline void __user *compat_alloc_user_space(long len) | 198 | static inline void __user *arch_compat_alloc_user_space(long len) |
199 | { | 199 | { |
200 | struct pt_regs *regs = task_pt_regs(current); | 200 | struct pt_regs *regs = task_pt_regs(current); |
201 | return (void __user *)regs->sp - len; | 201 | return (void __user *)regs->sp - len; |
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 306160e58b4..1d9cd27c292 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h | |||
@@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
205 | return (u32)(unsigned long)uptr; | 205 | return (u32)(unsigned long)uptr; |
206 | } | 206 | } |
207 | 207 | ||
208 | static inline void __user *compat_alloc_user_space(long len) | 208 | static inline void __user *arch_compat_alloc_user_space(long len) |
209 | { | 209 | { |
210 | struct pt_regs *regs = task_pt_regs(current); | 210 | struct pt_regs *regs = task_pt_regs(current); |
211 | return (void __user *)regs->sp - len; | 211 | return (void __user *)regs->sp - len; |