| summaryrefslogtreecommitdiff |
| author | Jeff Mahoney <jeffm@suse.de> | 2010-09-16 18:37:08 (GMT) |
|---|---|---|
| committer | Jeff Mahoney <jeffm@suse.de> | 2010-09-16 18:37:08 (GMT) |
| commit | 664a0ac1d4264279ad3ed00d1beac8688c31f3b9 (patch) (side-by-side diff) | |
| tree | f2afd8ad7bbf2474eeeeecae802d20aebd38a5e2 | |
| parent | a3abfe22d4ea07641e1cbf98e68a0215a08c96f5 (diff) | |
- compat: Make compat_alloc_user_space() incorporate the
access_ok() (CVE-2010-3081 bnc#639709).
| -rw-r--r-- | patches.fixes/compat-make-compat_alloc_user_space-incorporate-the-access_ok | 207 | ||||
| -rw-r--r-- | series.conf | 1 |
2 files changed, 208 insertions, 0 deletions
diff --git a/patches.fixes/compat-make-compat_alloc_user_space-incorporate-the-access_ok b/patches.fixes/compat-make-compat_alloc_user_space-incorporate-the-access_ok new file mode 100644 index 0000000..be0f1c8 --- a/dev/null +++ b/patches.fixes/compat-make-compat_alloc_user_space-incorporate-the-access_ok @@ -0,0 +1,207 @@ +From: H. Peter Anvin <hpa@linux.intel.com> +Date: Tue, 7 Sep 2010 23:16:18 +0000 (-0700) +Subject: compat: Make compat_alloc_user_space() incorporate the access_ok() +Git-commit: c41d68a513c71e35a14f66d71782d27a79a81ea6 +References: CVE-2010-3081 bnc#639709 +Patch-mainline: 2.6.36 +Introduced-by: Prior to 2.6.5 + +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> +Acked-by: Jeff Mahoney <jeffm@suse.com> +--- + + arch/ia64/include/asm/compat.h | 2 +- + arch/mips/include/asm/compat.h | 2 +- + arch/parisc/include/asm/compat.h | 2 +- + arch/powerpc/include/asm/compat.h | 2 +- + arch/s390/include/asm/compat.h | 2 +- + arch/sparc/include/asm/compat.h | 2 +- + arch/tile/include/asm/compat.h | 2 +- + arch/x86/include/asm/compat.h | 2 +- + include/linux/compat.h | 3 +++ + kernel/compat.c | 21 +++++++++++++++++++++ + 10 files changed, 32 insertions(+), 8 deletions(-) + +diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h +index f90edc8..9301a28 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) + } + + static __inline__ void __user * +-compat_alloc_user_space (long len) ++arch_compat_alloc_user_space (long len) + { + struct pt_regs *regs = task_pt_regs(current); + 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 613f691..dbc5106 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) + return (u32)(unsigned long)uptr; + } + +-static inline void __user *compat_alloc_user_space(long len) ++static inline void __user *arch_compat_alloc_user_space(long len) + { + struct pt_regs *regs = (struct pt_regs *) + ((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 02b77ba..efa0b60 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) + return (u32)(unsigned long)uptr; + } + +-static __inline__ void __user *compat_alloc_user_space(long len) ++static __inline__ void __user *arch_compat_alloc_user_space(long len) + { + struct pt_regs *regs = ¤t->thread.regs; + return (void __user *)regs->gr[30]; +diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h +index 396d21a..a11d4ea 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) + return (u32)(unsigned long)uptr; + } + +-static inline void __user *compat_alloc_user_space(long len) ++static inline void __user *arch_compat_alloc_user_space(long len) + { + struct pt_regs *regs = current->thread.regs; + unsigned long usp = regs->gpr[1]; +diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h +index 104f200..a875c2f 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) + + #endif + +-static inline void __user *compat_alloc_user_space(long len) ++static inline void __user *arch_compat_alloc_user_space(long len) + { + unsigned long stack; + +diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h +index 5016f76..6f57325 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) + return (u32)(unsigned long)uptr; + } + +-static inline void __user *compat_alloc_user_space(long len) ++static inline void __user *arch_compat_alloc_user_space(long len) + { + struct pt_regs *regs = current_thread_info()->kregs; + 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 5a34da6..345d81c 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) + return (long)(int)(long __force)uptr; + } + +-static inline void __user *compat_alloc_user_space(long len) ++static inline void __user *arch_compat_alloc_user_space(long len) + { + struct pt_regs *regs = task_pt_regs(current); + return (void __user *)regs->sp - len; +diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h +index 306160e..1d9cd27 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) + return (u32)(unsigned long)uptr; + } + +-static inline void __user *compat_alloc_user_space(long len) ++static inline void __user *arch_compat_alloc_user_space(long len) + { + struct pt_regs *regs = task_pt_regs(current); + return (void __user *)regs->sp - len; +diff --git a/include/linux/compat.h b/include/linux/compat.h +index 9ddc878..5778b55 100644 +--- a/include/linux/compat.h ++++ b/include/linux/compat.h +@@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type, + const struct compat_iovec __user *uvector, unsigned long nr_segs, + unsigned long fast_segs, struct iovec *fast_pointer, + struct iovec **ret_pointer); ++ ++extern void __user *compat_alloc_user_space(unsigned long len); ++ + #endif /* CONFIG_COMPAT */ + #endif /* _LINUX_COMPAT_H */ +diff --git a/kernel/compat.c b/kernel/compat.c +index e167efc..c9e2ec0 100644 +--- a/kernel/compat.c ++++ b/kernel/compat.c +@@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) + + return 0; + } ++ ++/* ++ * Allocate user-space memory for the duration of a single system call, ++ * in order to marshall parameters inside a compat thunk. ++ */ ++void __user *compat_alloc_user_space(unsigned long len) ++{ ++ void __user *ptr; ++ ++ /* If len would occupy more than half of the entire compat space... */ ++ if (unlikely(len > (((compat_uptr_t)~0) >> 1))) ++ return NULL; ++ ++ ptr = arch_compat_alloc_user_space(len); ++ ++ if (unlikely(!access_ok(VERIFY_WRITE, ptr, len))) ++ return NULL; ++ ++ return ptr; ++} ++EXPORT_SYMBOL_GPL(compat_alloc_user_space); diff --git a/series.conf b/series.conf index 07aee4f..79f294e 100644 --- a/series.conf +++ b/series.conf @@ -91,6 +91,7 @@ patches.fixes/make-note_interrupt-fast.diff patches.fixes/twl6030-fix-note_interrupt-call + patches.fixes/compat-make-compat_alloc_user_space-incorporate-the-access_ok ######################################################## # Architecture-specific patches. These used to be all |