[kernel] r15044 - in dists/lenny-security/linux-2.6/debian: . patches/bugfix/all patches/features/all/openvz patches/features/all/vserver patches/series

Dann Frazier dannf at alioth.debian.org
Wed Jan 27 16:52:32 UTC 2010


Author: dannf
Date: Wed Jan 27 16:52:30 2010
New Revision: 15044

Log:
* Fix several issues with mmap/mremap (CVE-2010-0291)

Added:
   dists/lenny-security/linux-2.6/debian/patches/bugfix/all/untangle-the-do_mremap-mess.patch
Modified:
   dists/lenny-security/linux-2.6/debian/changelog
   dists/lenny-security/linux-2.6/debian/patches/features/all/openvz/openvz.patch
   dists/lenny-security/linux-2.6/debian/patches/features/all/vserver/vs2.3.0.35.patch
   dists/lenny-security/linux-2.6/debian/patches/series/21lenny1

Modified: dists/lenny-security/linux-2.6/debian/changelog
==============================================================================
--- dists/lenny-security/linux-2.6/debian/changelog	Wed Jan 27 16:35:55 2010	(r15043)
+++ dists/lenny-security/linux-2.6/debian/changelog	Wed Jan 27 16:52:30 2010	(r15044)
@@ -4,6 +4,7 @@
   * mac80211: fix spurious delBA handling (CVE-2009-4027)
   * e1000: enhance frame fragment detection (CVE-2009-4536)
   * e1000e: enhance frame fragment detection (CVE-2009-4538)
+  * Fix several issues with mmap/mremap (CVE-2010-0291)
  
   [ Ben Hutchings ]
   * kernel/signal.c: fix kernel information leak with print-fatal-signals=1

Added: dists/lenny-security/linux-2.6/debian/patches/bugfix/all/untangle-the-do_mremap-mess.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/lenny-security/linux-2.6/debian/patches/bugfix/all/untangle-the-do_mremap-mess.patch	Wed Jan 27 16:52:30 2010	(r15044)
@@ -0,0 +1,2321 @@
+diff -urpN linux-source-2.6.26.orig/arch/alpha/kernel/osf_sys.c linux-source-2.6.26/arch/alpha/kernel/osf_sys.c
+--- linux-source-2.6.26.orig/arch/alpha/kernel/osf_sys.c	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/arch/alpha/kernel/osf_sys.c	2010-01-22 17:15:05.000000000 -0700
+@@ -178,25 +178,18 @@ SYSCALL_DEFINE6(osf_mmap, unsigned long,
+ 		unsigned long, prot, unsigned long, flags, unsigned long, fd,
+ 		unsigned long, off)
+ {
+-	struct file *file = NULL;
+-	unsigned long ret = -EBADF;
++	unsigned long ret = -EINVAL;
+ 
+ #if 0
+ 	if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
+ 		printk("%s: unimplemented OSF mmap flags %04lx\n", 
+ 			current->comm, flags);
+ #endif
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	down_write(&current->mm->mmap_sem);
+-	ret = do_mmap(file, addr, len, prot, flags, off);
+-	up_write(&current->mm->mmap_sem);
+-	if (file)
+-		fput(file);
++	if ((off + PAGE_ALIGN(len)) < off)
++		goto out;
++	if (off & ~PAGE_MASK)
++		goto out;
++	ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+  out:
+ 	return ret;
+ }
+diff -urpN linux-source-2.6.26.orig/arch/arm/kernel/calls.S linux-source-2.6.26/arch/arm/kernel/calls.S
+--- linux-source-2.6.26.orig/arch/arm/kernel/calls.S	2009-12-26 01:14:55.000000000 -0700
++++ linux-source-2.6.26/arch/arm/kernel/calls.S	2010-01-22 17:15:05.000000000 -0700
+@@ -172,7 +172,7 @@
+ /* 160 */	CALL(sys_sched_get_priority_min)
+ 		CALL(sys_sched_rr_get_interval)
+ 		CALL(sys_nanosleep)
+-		CALL(sys_arm_mremap)
++		CALL(sys_mremap)
+ 		CALL(sys_setresuid16)
+ /* 165 */	CALL(sys_getresuid16)
+ 		CALL(sys_ni_syscall)		/* vm86 */
+diff -urpN linux-source-2.6.26.orig/arch/arm/kernel/entry-common.S linux-source-2.6.26/arch/arm/kernel/entry-common.S
+--- linux-source-2.6.26.orig/arch/arm/kernel/entry-common.S	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/arm/kernel/entry-common.S	2010-01-22 17:15:05.000000000 -0700
+@@ -344,12 +344,12 @@ sys_mmap2:
+ 		tst	r5, #PGOFF_MASK
+ 		moveq	r5, r5, lsr #PAGE_SHIFT - 12
+ 		streq	r5, [sp, #4]
+-		beq	do_mmap2
++		beq	sys_mmap_pgoff
+ 		mov	r0, #-EINVAL
+ 		mov	pc, lr
+ #else
+ 		str	r5, [sp, #4]
+-		b	do_mmap2
++		b	sys_mmap_pgoff
+ #endif
+ 
+ ENTRY(pabort_ifar)
+diff -urpN linux-source-2.6.26.orig/arch/arm/kernel/sys_arm.c linux-source-2.6.26/arch/arm/kernel/sys_arm.c
+--- linux-source-2.6.26.orig/arch/arm/kernel/sys_arm.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/arm/kernel/sys_arm.c	2010-01-22 17:15:05.000000000 -0700
+@@ -30,41 +30,6 @@
+ 
+ #include <asm/uaccess.h>
+ 
+-extern unsigned long do_mremap(unsigned long addr, unsigned long old_len,
+-			       unsigned long new_len, unsigned long flags,
+-			       unsigned long new_addr);
+-
+-/* common code for old and new mmaps */
+-inline long do_mmap2(
+-	unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags,
+-	unsigned long fd, unsigned long pgoff)
+-{
+-	int error = -EINVAL;
+-	struct file * file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	if (flags & MAP_FIXED && addr < FIRST_USER_ADDRESS)
+-		goto out;
+-
+-	error = -EBADF;
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ struct mmap_arg_struct {
+ 	unsigned long addr;
+ 	unsigned long len;
+@@ -86,29 +51,11 @@ asmlinkage int old_mmap(struct mmap_arg_
+ 	if (a.offset & ~PAGE_MASK)
+ 		goto out;
+ 
+-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
++	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+ out:
+ 	return error;
+ }
+ 
+-asmlinkage unsigned long
+-sys_arm_mremap(unsigned long addr, unsigned long old_len,
+-	       unsigned long new_len, unsigned long flags,
+-	       unsigned long new_addr)
+-{
+-	unsigned long ret = -EINVAL;
+-
+-	if (flags & MREMAP_FIXED && new_addr < FIRST_USER_ADDRESS)
+-		goto out;
+-
+-	down_write(&current->mm->mmap_sem);
+-	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+-	up_write(&current->mm->mmap_sem);
+-
+-out:
+-	return ret;
+-}
+-
+ /*
+  * Perform the select(nd, in, out, ex, tv) and mmap() system
+  * calls.
+diff -urpN linux-source-2.6.26.orig/arch/arm/mm/mmap.c linux-source-2.6.26/arch/arm/mm/mmap.c
+--- linux-source-2.6.26.orig/arch/arm/mm/mmap.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/arm/mm/mmap.c	2010-01-22 17:15:05.000000000 -0700
+@@ -52,7 +52,8 @@ arch_get_unmapped_area(struct file *filp
+ 	 * We enforce the MAP_FIXED case.
+ 	 */
+ 	if (flags & MAP_FIXED) {
+-		if (aliasing && flags & MAP_SHARED && addr & (SHMLBA - 1))
++		if (aliasing && flags & MAP_SHARED &&
++		    (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
+ 			return -EINVAL;
+ 		return addr;
+ 	}
+diff -urpN linux-source-2.6.26.orig/arch/avr32/kernel/sys_avr32.c linux-source-2.6.26/arch/avr32/kernel/sys_avr32.c
+--- linux-source-2.6.26.orig/arch/avr32/kernel/sys_avr32.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/avr32/kernel/sys_avr32.c	2010-01-24 23:11:18.000000000 -0700
+@@ -5,38 +5,8 @@
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
+-#include <linux/errno.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/mm.h>
+ #include <linux/unistd.h>
+ 
+-#include <asm/mman.h>
+-#include <asm/uaccess.h>
+-
+-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+-			  unsigned long prot, unsigned long flags,
+-			  unsigned long fd, off_t offset)
+-{
+-	int error = -EBADF;
+-	struct file *file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			return error;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, offset);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-	return error;
+-}
+-
+ int kernel_execve(const char *file, char **argv, char **envp)
+ {
+ 	register long scno asm("r8") = __NR_execve;
+diff -urpN linux-source-2.6.26.orig/arch/avr32/kernel/syscall-stubs.S linux-source-2.6.26/arch/avr32/kernel/syscall-stubs.S
+--- linux-source-2.6.26.orig/arch/avr32/kernel/syscall-stubs.S	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/avr32/kernel/syscall-stubs.S	2010-01-24 23:11:51.000000000 -0700
+@@ -61,7 +61,7 @@ __sys_execve:
+ __sys_mmap2:
+ 	pushm	lr
+ 	st.w	--sp, ARG6
+-	rcall	sys_mmap2
++	call	sys_mmap_pgoff
+ 	sub	sp, -4
+ 	popm	pc
+ 
+diff -urpN linux-source-2.6.26.orig/arch/blackfin/kernel/sys_bfin.c linux-source-2.6.26/arch/blackfin/kernel/sys_bfin.c
+--- linux-source-2.6.26.orig/arch/blackfin/kernel/sys_bfin.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/blackfin/kernel/sys_bfin.c	2010-01-24 23:12:46.000000000 -0700
+@@ -45,39 +45,6 @@
+ #include <asm/cacheflush.h>
+ #include <asm/dma.h>
+ 
+-/* common code for old and new mmaps */
+-static inline long
+-do_mmap2(unsigned long addr, unsigned long len,
+-	 unsigned long prot, unsigned long flags,
+-	 unsigned long fd, unsigned long pgoff)
+-{
+-	int error = -EBADF;
+-	struct file *file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+- out:
+-	return error;
+-}
+-
+-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+-			  unsigned long prot, unsigned long flags,
+-			  unsigned long fd, unsigned long pgoff)
+-{
+-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+-}
+-
+ asmlinkage int sys_getpagesize(void)
+ {
+ 	return PAGE_SIZE;
+diff -urpN linux-source-2.6.26.orig/arch/blackfin/mach-common/entry.S linux-source-2.6.26/arch/blackfin/mach-common/entry.S
+--- linux-source-2.6.26.orig/arch/blackfin/mach-common/entry.S	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/blackfin/mach-common/entry.S	2010-01-22 17:15:08.000000000 -0700
+@@ -1220,7 +1220,7 @@ ENTRY(_sys_call_table)
+ 	.long _sys_ni_syscall	/* streams2 */
+ 	.long _sys_vfork		/* 190 */
+ 	.long _sys_getrlimit
+-	.long _sys_mmap2
++	.long _sys_mmap_pgoff
+ 	.long _sys_truncate64
+ 	.long _sys_ftruncate64
+ 	.long _sys_stat64	/* 195 */
+diff -urpN linux-source-2.6.26.orig/arch/cris/kernel/sys_cris.c linux-source-2.6.26/arch/cris/kernel/sys_cris.c
+--- linux-source-2.6.26.orig/arch/cris/kernel/sys_cris.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/cris/kernel/sys_cris.c	2010-01-22 17:15:08.000000000 -0700
+@@ -27,31 +27,6 @@
+ #include <asm/uaccess.h>
+ #include <asm/segment.h>
+ 
+-/* common code for old and new mmaps */
+-static inline long
+-do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+-        unsigned long flags, unsigned long fd, unsigned long pgoff)
+-{
+-        int error = -EBADF;
+-        struct file * file = NULL;
+-
+-        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-        if (!(flags & MAP_ANONYMOUS)) {
+-                file = fget(fd);
+-                if (!file)
+-                        goto out;
+-        }
+-
+-        down_write(&current->mm->mmap_sem);
+-        error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-        up_write(&current->mm->mmap_sem);
+-
+-        if (file)
+-                fput(file);
+-out:
+-        return error;
+-}
+-
+ asmlinkage unsigned long old_mmap(unsigned long __user *args)
+ {        
+ 	unsigned long buffer[6];
+@@ -64,7 +39,7 @@ asmlinkage unsigned long old_mmap(unsign
+ 	if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */
+ 		goto out;
+ 
+-	err = do_mmap2(buffer[0], buffer[1], buffer[2], buffer[3],
++	err = sys_mmap_pgoff(buffer[0], buffer[1], buffer[2], buffer[3],
+                        buffer[4], buffer[5] >> PAGE_SHIFT);
+ out:
+ 	return err;
+@@ -74,7 +49,8 @@ asmlinkage long
+ sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+           unsigned long flags, unsigned long fd, unsigned long pgoff)
+ {
+-        return do_mmap2(addr, len, prot, flags, fd, pgoff);
++	/* bug(?): 8Kb pages here */
++        return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
+ }
+ 
+ /*
+diff -urpN linux-source-2.6.26.orig/arch/frv/kernel/sys_frv.c linux-source-2.6.26/arch/frv/kernel/sys_frv.c
+--- linux-source-2.6.26.orig/arch/frv/kernel/sys_frv.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/frv/kernel/sys_frv.c	2010-01-24 23:15:23.000000000 -0700
+@@ -32,16 +32,6 @@ asmlinkage long sys_mmap2(unsigned long 
+ 			  unsigned long prot, unsigned long flags,
+ 			  unsigned long fd, unsigned long pgoff)
+ {
+-	int error = -EBADF;
+-	struct file * file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+ 	/* As with sparc32, make sure the shift for mmap2 is constant
+ 	   (12), no matter what PAGE_SIZE we have.... */
+ 
+@@ -50,62 +40,9 @@ asmlinkage long sys_mmap2(unsigned long 
+ 	if (pgoff & ((1<<(PAGE_SHIFT-12))-1))
+ 		return -EINVAL;
+ 
+-	pgoff >>= (PAGE_SHIFT - 12);
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+-#if 0 /* DAVIDM - do we want this */
+-struct mmap_arg_struct64 {
+-	__u32 addr;
+-	__u32 len;
+-	__u32 prot;
+-	__u32 flags;
+-	__u64 offset; /* 64 bits */
+-	__u32 fd;
+-};
+-
+-asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
+-{
+-	int error = -EFAULT;
+-	struct file * file = NULL;
+-	struct mmap_arg_struct64 a;
+-	unsigned long pgoff;
+-
+-	if (copy_from_user(&a, arg, sizeof(a)))
+-		return -EFAULT;
+-
+-	if ((long)a.offset & ~PAGE_MASK)
+-		return -EINVAL;
+-
+-	pgoff = a.offset >> PAGE_SHIFT;
+-	if ((a.offset >> PAGE_SHIFT) != pgoff)
+-		return -EINVAL;
+-
+-	if (!(a.flags & MAP_ANONYMOUS)) {
+-		error = -EBADF;
+-		file = fget(a.fd);
+-		if (!file)
+-			goto out;
+-	}
+-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
++	return sys_mmap_pgoff(addr, len, prot, flags, fd,
++			      pgoff >> (PAGE_SHIFT - 12));
+ }
+-#endif
+ 
+ /*
+  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+diff -urpN linux-source-2.6.26.orig/arch/h8300/kernel/syscalls.S linux-source-2.6.26/arch/h8300/kernel/syscalls.S
+--- linux-source-2.6.26.orig/arch/h8300/kernel/syscalls.S	2009-12-26 01:14:55.000000000 -0700
++++ linux-source-2.6.26/arch/h8300/kernel/syscalls.S	2010-01-22 17:15:08.000000000 -0700
+@@ -206,7 +206,7 @@ SYMBOL_NAME_LABEL(sys_call_table)	
+ 	.long SYMBOL_NAME(sys_ni_syscall)	/* streams2 */
+ 	.long SYMBOL_NAME(sys_vfork)            /* 190 */
+ 	.long SYMBOL_NAME(sys_getrlimit)
+-	.long SYMBOL_NAME(sys_mmap2)
++	.long SYMBOL_NAME(sys_mmap_pgoff)
+ 	.long SYMBOL_NAME(sys_truncate64)
+ 	.long SYMBOL_NAME(sys_ftruncate64)
+ 	.long SYMBOL_NAME(sys_stat64)		/* 195 */
+diff -urpN linux-source-2.6.26.orig/arch/h8300/kernel/sys_h8300.c linux-source-2.6.26/arch/h8300/kernel/sys_h8300.c
+--- linux-source-2.6.26.orig/arch/h8300/kernel/sys_h8300.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/h8300/kernel/sys_h8300.c	2010-01-22 17:15:08.000000000 -0700
+@@ -27,39 +27,6 @@
+ #include <asm/traps.h>
+ #include <asm/unistd.h>
+ 
+-/* common code for old and new mmaps */
+-static inline long do_mmap2(
+-	unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags,
+-	unsigned long fd, unsigned long pgoff)
+-{
+-	int error = -EBADF;
+-	struct file * file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags,
+-	unsigned long fd, unsigned long pgoff)
+-{
+-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+-}
+-
+ /*
+  * Perform the select(nd, in, out, ex, tv) and mmap() system
+  * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
+@@ -88,58 +55,12 @@ asmlinkage int old_mmap(struct mmap_arg_
+ 	if (a.offset & ~PAGE_MASK)
+ 		goto out;
+ 
+-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
++	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
++			       a.offset >> PAGE_SHIFT);
+ out:
+ 	return error;
+ }
+ 
+-#if 0 /* DAVIDM - do we want this */
+-struct mmap_arg_struct64 {
+-	__u32 addr;
+-	__u32 len;
+-	__u32 prot;
+-	__u32 flags;
+-	__u64 offset; /* 64 bits */
+-	__u32 fd;
+-};
+-
+-asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
+-{
+-	int error = -EFAULT;
+-	struct file * file = NULL;
+-	struct mmap_arg_struct64 a;
+-	unsigned long pgoff;
+-
+-	if (copy_from_user(&a, arg, sizeof(a)))
+-		return -EFAULT;
+-
+-	if ((long)a.offset & ~PAGE_MASK)
+-		return -EINVAL;
+-
+-	pgoff = a.offset >> PAGE_SHIFT;
+-	if ((a.offset >> PAGE_SHIFT) != pgoff)
+-		return -EINVAL;
+-
+-	if (!(a.flags & MAP_ANONYMOUS)) {
+-		error = -EBADF;
+-		file = fget(a.fd);
+-		if (!file)
+-			goto out;
+-	}
+-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-#endif
+-
+ struct sel_arg_struct {
+ 	unsigned long n;
+ 	fd_set *inp, *outp, *exp;
+diff -urpN linux-source-2.6.26.orig/arch/ia64/ia32/sys_ia32.c linux-source-2.6.26/arch/ia64/ia32/sys_ia32.c
+--- linux-source-2.6.26.orig/arch/ia64/ia32/sys_ia32.c	2009-12-26 01:14:55.000000000 -0700
++++ linux-source-2.6.26/arch/ia64/ia32/sys_ia32.c	2010-01-22 17:15:08.000000000 -0700
+@@ -893,6 +893,9 @@ ia32_do_mmap (struct file *file, unsigne
+ 
+ 	prot = get_prot32(prot);
+ 
++	/*if (flags & MAP_HUGETLB)
++		return -ENOMEM;*/
++
+ #if PAGE_SHIFT > IA32_PAGE_SHIFT
+ 	mutex_lock(&ia32_mmap_mutex);
+ 	{
+diff -urpN linux-source-2.6.26.orig/arch/ia64/kernel/sys_ia64.c linux-source-2.6.26/arch/ia64/kernel/sys_ia64.c
+--- linux-source-2.6.26.orig/arch/ia64/kernel/sys_ia64.c	2009-12-26 01:14:55.000000000 -0700
++++ linux-source-2.6.26/arch/ia64/kernel/sys_ia64.c	2010-01-22 17:15:08.000000000 -0700
+@@ -100,51 +100,7 @@ sys_getpagesize (void)
+ asmlinkage unsigned long
+ ia64_brk (unsigned long brk)
+ {
+-	unsigned long rlim, retval, newbrk, oldbrk;
+-	struct mm_struct *mm = current->mm;
+-
+-	/*
+-	 * Most of this replicates the code in sys_brk() except for an additional safety
+-	 * check and the clearing of r8.  However, we can't call sys_brk() because we need
+-	 * to acquire the mmap_sem before we can do the test...
+-	 */
+-	down_write(&mm->mmap_sem);
+-
+-	if (brk < mm->end_code)
+-		goto out;
+-	newbrk = PAGE_ALIGN(brk);
+-	oldbrk = PAGE_ALIGN(mm->brk);
+-	if (oldbrk == newbrk)
+-		goto set_brk;
+-
+-	/* Always allow shrinking brk. */
+-	if (brk <= mm->brk) {
+-		if (!do_munmap(mm, newbrk, oldbrk-newbrk))
+-			goto set_brk;
+-		goto out;
+-	}
+-
+-	/* Check against unimplemented/unmapped addresses: */
+-	if ((newbrk - oldbrk) > RGN_MAP_LIMIT || REGION_OFFSET(newbrk) > RGN_MAP_LIMIT)
+-		goto out;
+-
+-	/* Check against rlimit.. */
+-	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+-	if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
+-		goto out;
+-
+-	/* Check against existing mmap mappings. */
+-	if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
+-		goto out;
+-
+-	/* Ok, looks good - let it rip. */
+-	if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk)
+-		goto out;
+-set_brk:
+-	mm->brk = brk;
+-out:
+-	retval = mm->brk;
+-	up_write(&mm->mmap_sem);
++	unsigned long retval = sys_brk(brk);
+ 	force_successful_syscall_return();
+ 	return retval;
+ }
+@@ -185,39 +141,6 @@ int ia64_mmap_check(unsigned long addr, 
+ 	return 0;
+ }
+ 
+-static inline unsigned long
+-do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff)
+-{
+-	struct file *file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			return -EBADF;
+-
+-		if (!file->f_op || !file->f_op->mmap) {
+-			addr = -ENODEV;
+-			goto out;
+-		}
+-	}
+-
+-	/* Careful about overflows.. */
+-	len = PAGE_ALIGN(len);
+-	if (!len || len > TASK_SIZE) {
+-		addr = -EINVAL;
+-		goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-out:	if (file)
+-		fput(file);
+-	return addr;
+-}
+-
+ /*
+  * mmap2() is like mmap() except that the offset is expressed in units
+  * of PAGE_SIZE (instead of bytes).  This allows to mmap2() (pieces
+@@ -226,7 +149,7 @@ out:	if (file)
+ asmlinkage unsigned long
+ sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff)
+ {
+-	addr = do_mmap2(addr, len, prot, flags, fd, pgoff);
++	addr = sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
+ 	if (!IS_ERR((void *) addr))
+ 		force_successful_syscall_return();
+ 	return addr;
+@@ -238,7 +161,7 @@ sys_mmap (unsigned long addr, unsigned l
+ 	if (offset_in_page(off) != 0)
+ 		return -EINVAL;
+ 
+-	addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
++	addr = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+ 	if (!IS_ERR((void *) addr))
+ 		force_successful_syscall_return();
+ 	return addr;
+diff -urpN linux-source-2.6.26.orig/arch/m32r/kernel/syscall_table.S linux-source-2.6.26/arch/m32r/kernel/syscall_table.S
+--- linux-source-2.6.26.orig/arch/m32r/kernel/syscall_table.S	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/m32r/kernel/syscall_table.S	2010-01-22 17:15:08.000000000 -0700
+@@ -191,7 +191,7 @@ ENTRY(sys_call_table)
+ 	.long sys_ni_syscall		/* streams2 */
+ 	.long sys_vfork			/* 190 */
+ 	.long sys_getrlimit
+-	.long sys_mmap2
++	.long sys_mmap_pgoff
+ 	.long sys_truncate64
+ 	.long sys_ftruncate64
+ 	.long sys_stat64		/* 195 */
+diff -urpN linux-source-2.6.26.orig/arch/m32r/kernel/sys_m32r.c linux-source-2.6.26/arch/m32r/kernel/sys_m32r.c
+--- linux-source-2.6.26.orig/arch/m32r/kernel/sys_m32r.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/m32r/kernel/sys_m32r.c	2010-01-22 17:15:08.000000000 -0700
+@@ -76,30 +76,6 @@ asmlinkage int sys_tas(int __user *addr)
+ 	return oldval;
+ }
+ 
+-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags,
+-	unsigned long fd, unsigned long pgoff)
+-{
+-	int error = -EBADF;
+-	struct file *file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ /*
+  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+  *
+diff -urpN linux-source-2.6.26.orig/arch/m68k/kernel/sys_m68k.c linux-source-2.6.26/arch/m68k/kernel/sys_m68k.c
+--- linux-source-2.6.26.orig/arch/m68k/kernel/sys_m68k.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/m68k/kernel/sys_m68k.c	2010-01-22 17:15:08.000000000 -0700
+@@ -30,37 +30,16 @@
+ #include <asm/page.h>
+ #include <asm/unistd.h>
+ 
+-/* common code for old and new mmaps */
+-static inline long do_mmap2(
+-	unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags,
+-	unsigned long fd, unsigned long pgoff)
+-{
+-	int error = -EBADF;
+-	struct file * file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+ 	unsigned long prot, unsigned long flags,
+ 	unsigned long fd, unsigned long pgoff)
+ {
+-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
++	/*
++	 * This is wrong for sun3 - there PAGE_SIZE is 8Kb,
++	 * so we need to shift the argument down by 1; m68k mmap64(3)
++	 * (in libc) expects the last argument of mmap2 in 4Kb units.
++	 */
++	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
+ }
+ 
+ /*
+@@ -91,57 +70,11 @@ asmlinkage int old_mmap(struct mmap_arg_
+ 	if (a.offset & ~PAGE_MASK)
+ 		goto out;
+ 
+-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+-out:
+-	return error;
+-}
+-
+-#if 0
+-struct mmap_arg_struct64 {
+-	__u32 addr;
+-	__u32 len;
+-	__u32 prot;
+-	__u32 flags;
+-	__u64 offset; /* 64 bits */
+-	__u32 fd;
+-};
+-
+-asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
+-{
+-	int error = -EFAULT;
+-	struct file * file = NULL;
+-	struct mmap_arg_struct64 a;
+-	unsigned long pgoff;
+-
+-	if (copy_from_user(&a, arg, sizeof(a)))
+-		return -EFAULT;
+-
+-	if ((long)a.offset & ~PAGE_MASK)
+-		return -EINVAL;
+-
+-	pgoff = a.offset >> PAGE_SHIFT;
+-	if ((a.offset >> PAGE_SHIFT) != pgoff)
+-		return -EINVAL;
+-
+-	if (!(a.flags & MAP_ANONYMOUS)) {
+-		error = -EBADF;
+-		file = fget(a.fd);
+-		if (!file)
+-			goto out;
+-	}
+-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-	if (file)
+-		fput(file);
++	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
++			       a.offset >> PAGE_SHIFT);
+ out:
+ 	return error;
+ }
+-#endif
+ 
+ struct sel_arg_struct {
+ 	unsigned long n;
+diff -urpN linux-source-2.6.26.orig/arch/m68knommu/kernel/syscalltable.S linux-source-2.6.26/arch/m68knommu/kernel/syscalltable.S
+--- linux-source-2.6.26.orig/arch/m68knommu/kernel/syscalltable.S	2009-12-26 01:14:55.000000000 -0700
++++ linux-source-2.6.26/arch/m68knommu/kernel/syscalltable.S	2010-01-22 17:15:08.000000000 -0700
+@@ -210,7 +210,7 @@ ENTRY(sys_call_table)
+ 	.long sys_ni_syscall	/* streams2 */
+ 	.long sys_vfork		/* 190 */
+ 	.long sys_getrlimit
+-	.long sys_mmap2
++	.long sys_mmap_pgoff
+ 	.long sys_truncate64
+ 	.long sys_ftruncate64
+ 	.long sys_stat64	/* 195 */
+diff -urpN linux-source-2.6.26.orig/arch/m68knommu/kernel/sys_m68k.c linux-source-2.6.26/arch/m68knommu/kernel/sys_m68k.c
+--- linux-source-2.6.26.orig/arch/m68knommu/kernel/sys_m68k.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/m68knommu/kernel/sys_m68k.c	2010-01-22 17:15:08.000000000 -0700
+@@ -28,39 +28,6 @@
+ #include <asm/cacheflush.h>
+ #include <asm/unistd.h>
+ 
+-/* common code for old and new mmaps */
+-static inline long do_mmap2(
+-	unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags,
+-	unsigned long fd, unsigned long pgoff)
+-{
+-	int error = -EBADF;
+-	struct file * file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags,
+-	unsigned long fd, unsigned long pgoff)
+-{
+-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+-}
+-
+ /*
+  * Perform the select(nd, in, out, ex, tv) and mmap() system
+  * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
+@@ -89,9 +56,8 @@ asmlinkage int old_mmap(struct mmap_arg_
+ 	if (a.offset & ~PAGE_MASK)
+ 		goto out;
+ 
+-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
++	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
++				a.offset >> PAGE_SHIFT);
+ out:
+ 	return error;
+ }
+diff -urpN linux-source-2.6.26.orig/arch/mips/kernel/linux32.c linux-source-2.6.26/arch/mips/kernel/linux32.c
+--- linux-source-2.6.26.orig/arch/mips/kernel/linux32.c	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/arch/mips/kernel/linux32.c	2010-01-22 17:15:08.000000000 -0700
+@@ -104,28 +104,13 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long,
+ 	unsigned long, prot, unsigned long, flags, unsigned long, fd,
+ 	unsigned long, pgoff)
+ {
+-	struct file * file = NULL;
+ 	unsigned long error;
+ 
+ 	error = -EINVAL;
+ 	if (pgoff & (~PAGE_MASK >> 12))
+ 		goto out;
+-	pgoff >>= PAGE_SHIFT-12;
+-
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		error = -EBADF;
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-	if (file)
+-		fput(file);
+-
++	error = sys_mmap_pgoff(addr, len, prot, flags, fd,
++			       pgoff >> (PAGE_SHIFT-12));
+ out:
+ 	return error;
+ }
+diff -urpN linux-source-2.6.26.orig/arch/mips/kernel/syscall.c linux-source-2.6.26/arch/mips/kernel/syscall.c
+--- linux-source-2.6.26.orig/arch/mips/kernel/syscall.c	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/arch/mips/kernel/syscall.c	2010-01-22 17:15:08.000000000 -0700
+@@ -92,7 +92,8 @@ unsigned long arch_get_unmapped_area(str
+ 		 * We do not accept a shared mapping if it would violate
+ 		 * cache aliasing constraints.
+ 		 */
+-		if ((flags & MAP_SHARED) && (addr & shm_align_mask))
++		if ((flags & MAP_SHARED) &&
++		    ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
+ 			return -EINVAL;
+ 		return addr;
+ 	}
+@@ -128,31 +129,6 @@ unsigned long arch_get_unmapped_area(str
+ 	}
+ }
+ 
+-/* common code for old and new mmaps */
+-static inline unsigned long
+-do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+-        unsigned long flags, unsigned long fd, unsigned long pgoff)
+-{
+-	unsigned long error = -EBADF;
+-	struct file * file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
+ 	unsigned long, prot, unsigned long, flags, unsigned long,
+ 	fd, off_t, offset)
+@@ -163,7 +139,7 @@ SYSCALL_DEFINE6(mips_mmap, unsigned long
+ 	if (offset & ~PAGE_MASK)
+ 		goto out;
+ 
+-	result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
++	result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+ 
+ out:
+ 	return result;
+@@ -176,7 +152,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned lon
+ 	if (pgoff & (~PAGE_MASK >> 12))
+ 		return -EINVAL;
+ 
+-	return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
++	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
+ }
+ 
+ save_static_function(sys_fork);
+diff -urpN linux-source-2.6.26.orig/arch/mn10300/kernel/entry.S linux-source-2.6.26/arch/mn10300/kernel/entry.S
+--- linux-source-2.6.26.orig/arch/mn10300/kernel/entry.S	2009-12-26 01:14:55.000000000 -0700
++++ linux-source-2.6.26/arch/mn10300/kernel/entry.S	2010-01-22 17:15:08.000000000 -0700
+@@ -580,7 +580,7 @@ ENTRY(sys_call_table)
+ 	.long sys_ni_syscall	/* reserved for streams2 */
+ 	.long sys_vfork		/* 190 */
+ 	.long sys_getrlimit
+-	.long sys_mmap2
++	.long sys_mmap_pgoff
+ 	.long sys_truncate64
+ 	.long sys_ftruncate64
+ 	.long sys_stat64	/* 195 */
+diff -urpN linux-source-2.6.26.orig/arch/mn10300/kernel/sys_mn10300.c linux-source-2.6.26/arch/mn10300/kernel/sys_mn10300.c
+--- linux-source-2.6.26.orig/arch/mn10300/kernel/sys_mn10300.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/mn10300/kernel/sys_mn10300.c	2010-01-22 17:15:08.000000000 -0700
+@@ -26,47 +26,13 @@
+ 
+ #include <asm/uaccess.h>
+ 
+-#define MIN_MAP_ADDR	PAGE_SIZE	/* minimum fixed mmap address */
+-
+-/*
+- * memory mapping syscall
+- */
+-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+-			  unsigned long prot, unsigned long flags,
+-			  unsigned long fd, unsigned long pgoff)
+-{
+-	struct file *file = NULL;
+-	long error = -EINVAL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	if (flags & MAP_FIXED && addr < MIN_MAP_ADDR)
+-		goto out;
+-
+-	error = -EBADF;
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ asmlinkage long old_mmap(unsigned long addr, unsigned long len,
+ 			 unsigned long prot, unsigned long flags,
+ 			 unsigned long fd, unsigned long offset)
+ {
+ 	if (offset & ~PAGE_MASK)
+ 		return -EINVAL;
+-	return sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
++	return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+ }
+ 
+ struct sel_arg_struct {
+diff -urpN linux-source-2.6.26.orig/arch/parisc/kernel/sys_parisc.c linux-source-2.6.26/arch/parisc/kernel/sys_parisc.c
+--- linux-source-2.6.26.orig/arch/parisc/kernel/sys_parisc.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/parisc/kernel/sys_parisc.c	2010-01-22 17:15:08.000000000 -0700
+@@ -110,37 +110,14 @@ unsigned long arch_get_unmapped_area(str
+ 	return addr;
+ }
+ 
+-static unsigned long do_mmap2(unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags, unsigned long fd,
+-	unsigned long pgoff)
+-{
+-	struct file * file = NULL;
+-	unsigned long error = -EBADF;
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file != NULL)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
+ 	unsigned long prot, unsigned long flags, unsigned long fd,
+ 	unsigned long pgoff)
+ {
+ 	/* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
+ 	   we have. */
+-	return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
++	return sys_mmap_pgoff(addr, len, prot, flags, fd,
++			      pgoff >> (PAGE_SHIFT - 12));
+ }
+ 
+ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+@@ -148,7 +125,8 @@ asmlinkage unsigned long sys_mmap(unsign
+ 		unsigned long offset)
+ {
+ 	if (!(offset & ~PAGE_MASK)) {
+-		return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
++		return sys_mmap_pgoff(addr, len, prot, flags, fd,
++					offset >> PAGE_SHIFT);
+ 	} else {
+ 		return -EINVAL;
+ 	}
+diff -urpN linux-source-2.6.26.orig/arch/powerpc/kernel/syscalls.c linux-source-2.6.26/arch/powerpc/kernel/syscalls.c
+--- linux-source-2.6.26.orig/arch/powerpc/kernel/syscalls.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/powerpc/kernel/syscalls.c	2010-01-22 17:15:08.000000000 -0700
+@@ -140,7 +140,6 @@ static inline unsigned long do_mmap2(uns
+ 			unsigned long prot, unsigned long flags,
+ 			unsigned long fd, unsigned long off, int shift)
+ {
+-	struct file * file = NULL;
+ 	unsigned long ret = -EINVAL;
+ 
+ 	if (shift) {
+@@ -148,20 +147,8 @@ static inline unsigned long do_mmap2(uns
+ 			goto out;
+ 		off >>= shift;
+ 	}
+-		
+-	ret = -EBADF;
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		if (!(file = fget(fd)))
+-			goto out;
+-	}
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ 
+-	down_write(&current->mm->mmap_sem);
+-	ret = do_mmap_pgoff(file, addr, len, prot, flags, off);
+-	up_write(&current->mm->mmap_sem);
+-	if (file)
+-		fput(file);
++	ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off);
+ out:
+ 	return ret;
+ }
+diff -urpN linux-source-2.6.26.orig/arch/s390/kernel/compat_linux.c linux-source-2.6.26/arch/s390/kernel/compat_linux.c
+--- linux-source-2.6.26.orig/arch/s390/kernel/compat_linux.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/s390/kernel/compat_linux.c	2010-01-22 17:15:08.000000000 -0700
+@@ -843,38 +843,6 @@ struct mmap_arg_struct_emu31 {
+ 	u32	offset;
+ };
+ 
+-/* common code for old and new mmaps */
+-static inline long do_mmap2(
+-	unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags,
+-	unsigned long fd, unsigned long pgoff)
+-{
+-	struct file * file = NULL;
+-	unsigned long error = -EBADF;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) {
+-		/* Result is out of bounds.  */
+-		do_munmap(current->mm, addr, len);
+-		error = -ENOMEM;
+-	}
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:    
+-	return error;
+-}
+-
+-
+ asmlinkage unsigned long
+ old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
+ {
+@@ -888,7 +856,8 @@ old32_mmap(struct mmap_arg_struct_emu31 
+ 	if (a.offset & ~PAGE_MASK)
+ 		goto out;
+ 
+-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); 
++	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
++			       a.offset >> PAGE_SHIFT);
+ out:
+ 	return error;
+ }
+@@ -901,7 +870,7 @@ sys32_mmap2(struct mmap_arg_struct_emu31
+ 
+ 	if (copy_from_user(&a, arg, sizeof(a)))
+ 		goto out;
+-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
++	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+ out:
+ 	return error;
+ }
+diff -urpN linux-source-2.6.26.orig/arch/s390/kernel/sys_s390.c linux-source-2.6.26/arch/s390/kernel/sys_s390.c
+--- linux-source-2.6.26.orig/arch/s390/kernel/sys_s390.c	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/arch/s390/kernel/sys_s390.c	2010-01-22 17:15:08.000000000 -0700
+@@ -33,32 +33,6 @@
+ #include <asm/uaccess.h>
+ #include "entry.h"
+ 
+-/* common code for old and new mmaps */
+-static inline long do_mmap2(
+-	unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags,
+-	unsigned long fd, unsigned long pgoff)
+-{
+-	long error = -EBADF;
+-	struct file * file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ /*
+  * Perform the select(nd, in, out, ex, tv) and mmap() system
+  * calls. Linux for S/390 isn't able to handle more than 5
+@@ -82,7 +56,7 @@ SYSCALL_DEFINE1(mmap2, struct mmap_arg_s
+ 
+ 	if (copy_from_user(&a, arg, sizeof(a)))
+ 		goto out;
+-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
++	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+ out:
+ 	return error;
+ }
+@@ -99,7 +73,7 @@ SYSCALL_DEFINE1(s390_old_mmap, struct mm
+ 	if (a.offset & ~PAGE_MASK)
+ 		goto out;
+ 
+-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
++	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+ out:
+ 	return error;
+ }
+diff -urpN linux-source-2.6.26.orig/arch/sh/kernel/sys_sh.c linux-source-2.6.26/arch/sh/kernel/sys_sh.c
+--- linux-source-2.6.26.orig/arch/sh/kernel/sys_sh.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/sh/kernel/sys_sh.c	2010-01-24 23:18:02.000000000 -0700
+@@ -49,7 +49,8 @@ unsigned long arch_get_unmapped_area(str
+ 		/* We do not accept a shared mapping if it would violate
+ 		 * cache aliasing constraints.
+ 		 */
+-		if ((flags & MAP_SHARED) && (addr & shm_align_mask))
++		if ((flags & MAP_SHARED) &&
++		    ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
+ 			return -EINVAL;
+ 		return addr;
+ 	}
+@@ -117,44 +118,20 @@ full_search:
+ }
+ #endif /* CONFIG_MMU */
+ 
+-static inline long
+-do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+-	 unsigned long flags, int fd, unsigned long pgoff)
+-{
+-	int error = -EBADF;
+-	struct file *file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ asmlinkage int old_mmap(unsigned long addr, unsigned long len,
+ 	unsigned long prot, unsigned long flags,
+ 	int fd, unsigned long off)
+ {
+ 	if (off & ~PAGE_MASK)
+ 		return -EINVAL;
+-	return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT);
++	return sys_mmap_pgoff(addr, len, prot, flags, fd, off>>PAGE_SHIFT);
+ }
+ 
+ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+ 	unsigned long prot, unsigned long flags,
+ 	unsigned long fd, unsigned long pgoff)
+ {
+-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
++	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
+ }
+ 
+ /*
+diff -urpN linux-source-2.6.26.orig/arch/sparc/kernel/sys_sparc.c linux-source-2.6.26/arch/sparc/kernel/sys_sparc.c
+--- linux-source-2.6.26.orig/arch/sparc/kernel/sys_sparc.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/sparc/kernel/sys_sparc.c	2010-01-24 22:45:57.000000000 -0700
+@@ -45,7 +45,8 @@ unsigned long arch_get_unmapped_area(str
+ 		/* We do not accept a shared mapping if it would violate
+ 		 * cache aliasing constraints.
+ 		 */
+-		if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
++		if ((flags & MAP_SHARED) &&
++		    ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
+ 			return -EINVAL;
+ 		return addr;
+ 	}
+@@ -79,15 +80,6 @@ unsigned long arch_get_unmapped_area(str
+ 	}
+ }
+ 
+-asmlinkage unsigned long sparc_brk(unsigned long brk)
+-{
+-	if(ARCH_SUN4C_SUN4) {
+-		if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000))
+-			return current->mm->brk;
+-	}
+-	return sys_brk(brk);
+-}
+-
+ /*
+  * sys_pipe() is the normal C calling standard for creating
+  * a pipe. It's not the way unix traditionally does this, though.
+@@ -234,31 +226,6 @@ int sparc_mmap_check(unsigned long addr,
+ }
+ 
+ /* Linux version of mmap */
+-static unsigned long do_mmap2(unsigned long addr, unsigned long len,
+-	unsigned long prot, unsigned long flags, unsigned long fd,
+-	unsigned long pgoff)
+-{
+-	struct file * file = NULL;
+-	unsigned long retval = -EBADF;
+-
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	len = PAGE_ALIGN(len);
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-
+-	down_write(&current->mm->mmap_sem);
+-	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return retval;
+-}
+ 
+ asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
+ 	unsigned long prot, unsigned long flags, unsigned long fd,
+@@ -266,14 +233,16 @@ asmlinkage unsigned long sys_mmap2(unsig
+ {
+ 	/* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
+ 	   we have. */
+-	return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
++	return sys_mmap_pgoff(addr, len, prot, flags, fd,
++			      pgoff >> (PAGE_SHIFT - 12));
+ }
+ 
+ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+ 	unsigned long prot, unsigned long flags, unsigned long fd,
+ 	unsigned long off)
+ {
+-	return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
++	/* no alignment check? */
++	return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+ }
+ 
+ long sparc_remap_file_pages(unsigned long start, unsigned long size,
+@@ -287,27 +256,6 @@ long sparc_remap_file_pages(unsigned lon
+ 				    (pgoff >> (PAGE_SHIFT - 12)), flags);
+ }
+ 
+-extern unsigned long do_mremap(unsigned long addr,
+-	unsigned long old_len, unsigned long new_len,
+-	unsigned long flags, unsigned long new_addr);
+-                
+-asmlinkage unsigned long sparc_mremap(unsigned long addr,
+-	unsigned long old_len, unsigned long new_len,
+-	unsigned long flags, unsigned long new_addr)
+-{
+-	unsigned long ret = -EINVAL;
+-
+-	if (unlikely(sparc_mmap_check(addr, old_len)))
+-		goto out;
+-	if (unlikely(sparc_mmap_check(new_addr, new_len)))
+-		goto out;
+-	down_write(&current->mm->mmap_sem);
+-	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+-	up_write(&current->mm->mmap_sem);
+-out:
+-	return ret;       
+-}
+-
+ /* we come to here via sys_nis_syscall so it can setup the regs argument */
+ asmlinkage unsigned long
+ c_sys_nis_syscall (struct pt_regs *regs)
+diff -urpN linux-source-2.6.26.orig/arch/sparc/kernel/systbls.S linux-source-2.6.26/arch/sparc/kernel/systbls.S
+--- linux-source-2.6.26.orig/arch/sparc/kernel/systbls.S	2009-12-26 01:14:55.000000000 -0700
++++ linux-source-2.6.26/arch/sparc/kernel/systbls.S	2010-01-24 22:58:13.000000000 -0700
+@@ -19,7 +19,7 @@ sys_call_table:
+ /*0*/	.long sys_restart_syscall, sys_exit, sys_fork, sys_read, sys_write
+ /*5*/	.long sys_open, sys_close, sys_wait4, sys_creat, sys_link
+ /*10*/  .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod
+-/*15*/	.long sys_chmod, sys_lchown16, sparc_brk, sys_nis_syscall, sys_lseek
++/*15*/	.long sys_chmod, sys_lchown16, sys_brk, sys_nis_syscall, sys_lseek
+ /*20*/	.long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
+ /*25*/	.long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
+ /*30*/	.long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
+@@ -67,7 +67,7 @@ sys_call_table:
+ /*235*/	.long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
+ /*240*/	.long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
+ /*245*/	.long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
+-/*250*/	.long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
++/*250*/	.long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+ /*255*/	.long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+ /*260*/	.long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
+ /*265*/	.long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
+diff -urpN linux-source-2.6.26.orig/arch/sparc64/kernel/sys_sparc.c linux-source-2.6.26/arch/sparc64/kernel/sys_sparc.c
+--- linux-source-2.6.26.orig/arch/sparc64/kernel/sys_sparc.c	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/arch/sparc64/kernel/sys_sparc.c	2010-01-24 22:50:20.000000000 -0700
+@@ -316,10 +316,14 @@ bottomup:
+ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags)
+ {
+ 	unsigned long align_goal, addr = -ENOMEM;
++	unsigned long (*get_area)(struct file *, unsigned long,
++				  unsigned long, unsigned long, unsigned long);
++
++	get_area = current->mm->get_unmapped_area;
+ 
+ 	if (flags & MAP_FIXED) {
+ 		/* Ok, don't mess with it. */
+-		return get_unmapped_area(NULL, orig_addr, len, pgoff, flags);
++		return get_area(NULL, orig_addr, len, pgoff, flags);
+ 	}
+ 	flags &= ~MAP_SHARED;
+ 
+@@ -332,7 +336,7 @@ unsigned long get_fb_unmapped_area(struc
+ 		align_goal = (64UL * 1024);
+ 
+ 	do {
+-		addr = get_unmapped_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags);
++		addr = get_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags);
+ 		if (!(addr & ~PAGE_MASK)) {
+ 			addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL);
+ 			break;
+@@ -350,7 +354,7 @@ unsigned long get_fb_unmapped_area(struc
+ 	 * be obtained.
+ 	 */
+ 	if (addr & ~PAGE_MASK)
+-		addr = get_unmapped_area(NULL, orig_addr, len, pgoff, flags);
++		addr = get_area(NULL, orig_addr, len, pgoff, flags);
+ 
+ 	return addr;
+ }
+@@ -397,18 +401,6 @@ void arch_pick_mmap_layout(struct mm_str
+ 	}
+ }
+ 
+-SYSCALL_DEFINE1(sparc_brk, unsigned long, brk)
+-{
+-	/* People could try to be nasty and use ta 0x6d in 32bit programs */
+-	if (test_thread_flag(TIF_32BIT) && brk >= STACK_TOP32)
+-		return current->mm->brk;
+-
+-	if (unlikely(straddles_64bit_va_hole(current->mm->brk, brk)))
+-		return current->mm->brk;
+-
+-	return sys_brk(brk);
+-}
+-                                                                
+ /*
+  * sys_pipe() is the normal C calling standard for creating
+  * a pipe. It's not the way unix traditionally does this, though.
+@@ -566,23 +558,13 @@ SYSCALL_DEFINE6(mmap, unsigned long, add
+ 		unsigned long, prot, unsigned long, flags, unsigned long, fd,
+ 		unsigned long, off)
+ {
+-	struct file * file = NULL;
+-	unsigned long retval = -EBADF;
+-
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	len = PAGE_ALIGN(len);
++	unsigned long retval = -EINVAL;
+ 
+-	down_write(&current->mm->mmap_sem);
+-	retval = do_mmap(file, addr, len, prot, flags, off);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
++	if ((off + PAGE_ALIGN(len)) < off)
++		goto out;
++	if (off & ~PAGE_MASK)
++		goto out;
++	retval = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+ out:
+ 	return retval;
+ }
+@@ -612,12 +594,6 @@ SYSCALL_DEFINE5(64_mremap, unsigned long
+ 
+ 	if (test_thread_flag(TIF_32BIT))
+ 		goto out;
+-	if (unlikely(new_len >= VA_EXCLUDE_START))
+-		goto out;
+-	if (unlikely(sparc64_mmap_check(addr, old_len)))
+-		goto out;
+-	if (unlikely(sparc64_mmap_check(new_addr, new_len)))
+-		goto out;
+ 
+ 	down_write(&current->mm->mmap_sem);
+ 	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+diff -urpN linux-source-2.6.26.orig/arch/sparc64/kernel/systbls.h linux-source-2.6.26/arch/sparc64/kernel/systbls.h
+--- linux-source-2.6.26.orig/arch/sparc64/kernel/systbls.h	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/arch/sparc64/kernel/systbls.h	2010-01-24 23:00:08.000000000 -0700
+@@ -8,7 +8,6 @@
+ #include <asm/signal.h>
+ 
+ extern asmlinkage unsigned long sys_getpagesize(void);
+-extern asmlinkage unsigned long sparc_brk(unsigned long brk);
+ extern asmlinkage long sparc_pipe(struct pt_regs *regs);
+ extern asmlinkage long sys_ipc(unsigned int call, int first,
+ 			       unsigned long second,
+diff -urpN linux-source-2.6.26.orig/arch/sparc64/kernel/systbls.S linux-source-2.6.26/arch/sparc64/kernel/systbls.S
+--- linux-source-2.6.26.orig/arch/sparc64/kernel/systbls.S	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/arch/sparc64/kernel/systbls.S	2010-01-24 22:59:03.000000000 -0700
+@@ -21,7 +21,7 @@ sys_call_table32:
+ /*0*/	.word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write
+ /*5*/	.word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link
+ /*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
+-/*15*/	.word sys_chmod, sys32_lchown16, sys_sparc_brk, sys32_perfctr, sys32_lseek
++/*15*/	.word sys_chmod, sys_lchown16, sys_brk, sys32_perfctr, sys32_lseek
+ /*20*/	.word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16
+ /*25*/	.word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
+ /*30*/	.word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
+@@ -94,7 +94,7 @@ sys_call_table:
+ /*0*/	.word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write
+ /*5*/	.word sys_open, sys_close, sys_wait4, sys_creat, sys_link
+ /*10*/  .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod
+-/*15*/	.word sys_chmod, sys_lchown, sys_sparc_brk, sys_perfctr, sys_lseek
++/*15*/	.word sys_chmod, sys_lchown, sys_brk, sys_perfctr, sys_lseek
+ /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
+ /*25*/	.word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
+ /*30*/	.word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
+diff -urpN linux-source-2.6.26.orig/arch/um/include/sysdep-i386/syscalls.h linux-source-2.6.26/arch/um/include/sysdep-i386/syscalls.h
+--- linux-source-2.6.26.orig/arch/um/include/sysdep-i386/syscalls.h	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/um/include/sysdep-i386/syscalls.h	2010-01-22 17:30:51.000000000 -0700
+@@ -20,7 +20,3 @@ extern syscall_handler_t *sys_call_table
+ #define EXECUTE_SYSCALL(syscall, regs) \
+ 	((long (*)(struct syscall_args)) \
+ 	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
+-
+-extern long sys_mmap2(unsigned long addr, unsigned long len,
+-		      unsigned long prot, unsigned long flags,
+-		      unsigned long fd, unsigned long pgoff);
+diff -urpN linux-source-2.6.26.orig/arch/um/kernel/syscall.c linux-source-2.6.26/arch/um/kernel/syscall.c
+--- linux-source-2.6.26.orig/arch/um/kernel/syscall.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/um/kernel/syscall.c	2010-01-22 17:15:08.000000000 -0700
+@@ -8,6 +8,7 @@
+ #include "linux/mm.h"
+ #include "linux/sched.h"
+ #include "linux/utsname.h"
++#include "linux/syscalls.h"
+ #include "asm/current.h"
+ #include "asm/mman.h"
+ #include "asm/uaccess.h"
+@@ -36,31 +37,6 @@ long sys_vfork(void)
+ 	return ret;
+ }
+ 
+-/* common code for old and new mmaps */
+-long sys_mmap2(unsigned long addr, unsigned long len,
+-	       unsigned long prot, unsigned long flags,
+-	       unsigned long fd, unsigned long pgoff)
+-{
+-	long error = -EBADF;
+-	struct file * file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+- out:
+-	return error;
+-}
+-
+ long old_mmap(unsigned long addr, unsigned long len,
+ 	      unsigned long prot, unsigned long flags,
+ 	      unsigned long fd, unsigned long offset)
+@@ -69,7 +45,7 @@ long old_mmap(unsigned long addr, unsign
+ 	if (offset & ~PAGE_MASK)
+ 		goto out;
+ 
+-	err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
++	err = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+  out:
+ 	return err;
+ }
+diff -urpN linux-source-2.6.26.orig/arch/x86/ia32/ia32entry.S linux-source-2.6.26/arch/x86/ia32/ia32entry.S
+--- linux-source-2.6.26.orig/arch/x86/ia32/ia32entry.S	2009-12-26 01:14:58.000000000 -0700
++++ linux-source-2.6.26/arch/x86/ia32/ia32entry.S	2010-01-22 17:15:08.000000000 -0700
+@@ -600,7 +600,7 @@ ia32_sys_call_table:
+ 	.quad quiet_ni_syscall		/* streams2 */
+ 	.quad stub32_vfork            /* 190 */
+ 	.quad compat_sys_getrlimit
+-	.quad sys32_mmap2
++	.quad sys_mmap_pgoff
+ 	.quad sys32_truncate64
+ 	.quad sys32_ftruncate64
+ 	.quad sys32_stat64		/* 195 */
+diff -urpN linux-source-2.6.26.orig/arch/x86/ia32/sys_ia32.c linux-source-2.6.26/arch/x86/ia32/sys_ia32.c
+--- linux-source-2.6.26.orig/arch/x86/ia32/sys_ia32.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/x86/ia32/sys_ia32.c	2010-01-22 17:15:08.000000000 -0700
+@@ -199,9 +199,6 @@ struct mmap_arg_struct {
+ asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg)
+ {
+ 	struct mmap_arg_struct a;
+-	struct file *file = NULL;
+-	unsigned long retval;
+-	struct mm_struct *mm ;
+ 
+ 	if (copy_from_user(&a, arg, sizeof(a)))
+ 		return -EFAULT;
+@@ -209,22 +206,8 @@ asmlinkage long sys32_mmap(struct mmap_a
+ 	if (a.offset & ~PAGE_MASK)
+ 		return -EINVAL;
+ 
+-	if (!(a.flags & MAP_ANONYMOUS)) {
+-		file = fget(a.fd);
+-		if (!file)
+-			return -EBADF;
+-	}
+-
+-	mm = current->mm;
+-	down_write(&mm->mmap_sem);
+-	retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags,
++	return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+ 			       a.offset>>PAGE_SHIFT);
+-	if (file)
+-		fput(file);
+-
+-	up_write(&mm->mmap_sem);
+-
+-	return retval;
+ }
+ 
+ asmlinkage long sys32_mprotect(unsigned long start, size_t len,
+@@ -670,30 +653,6 @@ asmlinkage long sys32_sendfile(int out_f
+ 	return ret;
+ }
+ 
+-asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
+-			    unsigned long prot, unsigned long flags,
+-			    unsigned long fd, unsigned long pgoff)
+-{
+-	struct mm_struct *mm = current->mm;
+-	unsigned long error;
+-	struct file *file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			return -EBADF;
+-	}
+-
+-	down_write(&mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-	return error;
+-}
+-
+ asmlinkage long sys32_olduname(struct oldold_utsname __user *name)
+ {
+ 	char *arch = "x86_64";
+diff -urpN linux-source-2.6.26.orig/arch/x86/kernel/syscall_table_32.S linux-source-2.6.26/arch/x86/kernel/syscall_table_32.S
+--- linux-source-2.6.26.orig/arch/x86/kernel/syscall_table_32.S	2009-12-26 01:14:55.000000000 -0700
++++ linux-source-2.6.26/arch/x86/kernel/syscall_table_32.S	2010-01-22 17:15:08.000000000 -0700
+@@ -191,7 +191,7 @@ ENTRY(sys_call_table)
+ 	.long sys_ni_syscall	/* reserved for streams2 */
+ 	.long sys_vfork		/* 190 */
+ 	.long sys_getrlimit
+-	.long sys_mmap2
++	.long sys_mmap_pgoff
+ 	.long sys_truncate64
+ 	.long sys_ftruncate64
+ 	.long sys_stat64	/* 195 */
+diff -urpN linux-source-2.6.26.orig/arch/x86/kernel/sys_i386_32.c linux-source-2.6.26/arch/x86/kernel/sys_i386_32.c
+--- linux-source-2.6.26.orig/arch/x86/kernel/sys_i386_32.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/x86/kernel/sys_i386_32.c	2010-01-22 17:15:08.000000000 -0700
+@@ -22,31 +22,6 @@
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
+ 
+-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+-			  unsigned long prot, unsigned long flags,
+-			  unsigned long fd, unsigned long pgoff)
+-{
+-	int error = -EBADF;
+-	struct file *file = NULL;
+-	struct mm_struct *mm = current->mm;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ /*
+  * Perform the select(nd, in, out, ex, tv) and mmap() system
+  * calls. Linux/i386 didn't use to be able to handle more than
+@@ -75,7 +50,7 @@ asmlinkage int old_mmap(struct mmap_arg_
+ 	if (a.offset & ~PAGE_MASK)
+ 		goto out;
+ 
+-	err = sys_mmap2(a.addr, a.len, a.prot, a.flags,
++	err = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags,
+ 			a.fd, a.offset >> PAGE_SHIFT);
+ out:
+ 	return err;
+diff -urpN linux-source-2.6.26.orig/arch/x86/kernel/sys_x86_64.c linux-source-2.6.26/arch/x86/kernel/sys_x86_64.c
+--- linux-source-2.6.26.orig/arch/x86/kernel/sys_x86_64.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/x86/kernel/sys_x86_64.c	2010-01-22 17:27:43.000000000 -0700
+@@ -21,26 +21,11 @@ asmlinkage long sys_mmap(unsigned long a
+ 	unsigned long fd, unsigned long off)
+ {
+ 	long error;
+-	struct file * file;
+-
+ 	error = -EINVAL;
+ 	if (off & ~PAGE_MASK)
+ 		goto out;
+ 
+-	error = -EBADF;
+-	file = NULL;
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
++	error = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+ out:
+ 	return error;
+ }
+diff -urpN linux-source-2.6.26.orig/arch/xtensa/kernel/syscall.c linux-source-2.6.26/arch/xtensa/kernel/syscall.c
+--- linux-source-2.6.26.orig/arch/xtensa/kernel/syscall.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/arch/xtensa/kernel/syscall.c	2010-01-22 17:15:08.000000000 -0700
+@@ -57,31 +57,6 @@ asmlinkage long xtensa_pipe(int __user *
+ 	return error;
+ }
+ 
+-
+-asmlinkage long xtensa_mmap2(unsigned long addr, unsigned long len,
+-   			     unsigned long prot, unsigned long flags,
+-			     unsigned long fd, unsigned long pgoff)
+-{
+-	int error = -EBADF;
+-	struct file * file = NULL;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+-	up_write(&current->mm->mmap_sem);
+-
+-	if (file)
+-		fput(file);
+-out:
+-	return error;
+-}
+-
+ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
+ {
+ 	unsigned long ret;
+diff -urpN linux-source-2.6.26.orig/include/asm-arm/mman.h linux-source-2.6.26/include/asm-arm/mman.h
+--- linux-source-2.6.26.orig/include/asm-arm/mman.h	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/include/asm-arm/mman.h	2010-01-22 17:15:05.000000000 -0700
+@@ -1,4 +1,7 @@
+ #ifndef __ARM_MMAN_H__
++
++#define arch_mmap_check(addr, len, flags) \
++	(((flags) & MAP_FIXED && (addr) < FIRST_USER_ADDRESS) ? -EINVAL : 0)
+ #define __ARM_MMAN_H__
+ 
+ #include <asm-generic/mman.h>
+diff -urpN linux-source-2.6.26.orig/include/asm-mn10300/mman.h linux-source-2.6.26/include/asm-mn10300/mman.h
+--- linux-source-2.6.26.orig/include/asm-mn10300/mman.h	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/include/asm-mn10300/mman.h	2010-01-22 17:15:08.000000000 -0700
+@@ -1,4 +1,9 @@
+ /* MN10300 Constants for mmap and co.
++
++#define MIN_MAP_ADDR	PAGE_SIZE	/* minimum fixed mmap address */
++
++#define arch_mmap_check(addr, len, flags) \
++	(((flags) & MAP_FIXED && (addr) < MIN_MAP_ADDR) ? -EINVAL : 0)
+  *
+  * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+diff -urpN linux-source-2.6.26.orig/include/asm-xtensa/syscall.h linux-source-2.6.26/include/asm-xtensa/syscall.h
+--- linux-source-2.6.26.orig/include/asm-xtensa/syscall.h	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/include/asm-xtensa/syscall.h	2010-01-22 17:15:08.000000000 -0700
+@@ -13,8 +13,6 @@ struct sigaction;
+ asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
+ asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
+ asmlinkage long xtensa_pipe(int __user *);
+-asmlinkage long xtensa_mmap2(unsigned long, unsigned long, unsigned long,
+-    			     unsigned long, unsigned long, unsigned long);
+ asmlinkage long xtensa_ptrace(long, long, long, long);
+ asmlinkage long xtensa_sigreturn(struct pt_regs*);
+ asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
+diff -urpN linux-source-2.6.26.orig/include/asm-xtensa/unistd.h linux-source-2.6.26/include/asm-xtensa/unistd.h
+--- linux-source-2.6.26.orig/include/asm-xtensa/unistd.h	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/include/asm-xtensa/unistd.h	2010-01-22 17:15:08.000000000 -0700
+@@ -189,7 +189,7 @@ __SYSCALL( 79, sys_fremovexattr, 2)
+ /* File Map / Shared Memory Operations */
+ 
+ #define __NR_mmap2 				 80
+-__SYSCALL( 80, xtensa_mmap2, 6)
++__SYSCALL( 80, sys_mmap_pgoff, 6)
+ #define __NR_munmap 				 81
+ __SYSCALL( 81, sys_munmap, 2)
+ #define __NR_mprotect 				 82
+diff -urpN linux-source-2.6.26.orig/include/linux/syscalls.h linux-source-2.6.26/include/linux/syscalls.h
+--- linux-source-2.6.26.orig/include/linux/syscalls.h	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/include/linux/syscalls.h	2010-01-22 17:33:52.000000000 -0700
+@@ -686,6 +686,10 @@ asmlinkage long sys_ppoll(struct pollfd 
+ asmlinkage long sys_pipe2(int __user *, int);
+ asmlinkage long sys_pipe(int __user *);
+ 
++asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
++			unsigned long prot, unsigned long flags,
++			unsigned long fd, unsigned long pgoff);
++
+ int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
+ 
+ #endif
+diff -urpN linux-source-2.6.26.orig/ipc/shm.c linux-source-2.6.26/ipc/shm.c
+--- linux-source-2.6.26.orig/ipc/shm.c	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/ipc/shm.c	2010-01-22 17:18:51.000000000 -0700
+@@ -304,28 +304,28 @@ static unsigned long shm_get_unmapped_ar
+ 	unsigned long flags)
+ {
+ 	struct shm_file_data *sfd = shm_file_data(file);
+-	return get_unmapped_area(sfd->file, addr, len, pgoff, flags);
+-}
+-
+-int is_file_shm_hugepages(struct file *file)
+-{
+-	int ret = 0;
+-
+-	if (file->f_op == &shm_file_operations) {
+-		struct shm_file_data *sfd;
+-		sfd = shm_file_data(file);
+-		ret = is_file_hugepages(sfd->file);
+-	}
+-	return ret;
++	return sfd->file->f_op->get_unmapped_area(sfd->file, addr, len,
++						pgoff, flags);
+ }
+ 
+ static const struct file_operations shm_file_operations = {
+ 	.mmap		= shm_mmap,
+ 	.fsync		= shm_fsync,
+ 	.release	= shm_release,
++};
++
++static const struct file_operations shm_file_operations_huge = {
++	.mmap		= shm_mmap,
++	.fsync		= shm_fsync,
++	.release	= shm_release,
+ 	.get_unmapped_area	= shm_get_unmapped_area,
+ };
+ 
++int is_file_shm_hugepages(struct file *file)
++{
++	return file->f_op == &shm_file_operations_huge;
++}
++
+ static struct vm_operations_struct shm_vm_ops = {
+ 	.open	= shm_open,	/* callback for a new vm-area open */
+ 	.close	= shm_close,	/* callback for when the vm-area is released */
+@@ -898,7 +898,10 @@ long do_shmat(int shmid, char __user *sh
+ 	if (!sfd)
+ 		goto out_put_dentry;
+ 
+-	file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations);
++	file = alloc_file(path.mnt, path.dentry, f_mode,
++			is_file_hugepages(shp->shm_file) ?
++				&shm_file_operations_huge :
++				&shm_file_operations);
+ 	if (!file)
+ 		goto out_free;
+ 
+diff -urpN linux-source-2.6.26.orig/mm/mmap.c linux-source-2.6.26/mm/mmap.c
+--- linux-source-2.6.26.orig/mm/mmap.c	2009-12-26 01:14:57.000000000 -0700
++++ linux-source-2.6.26/mm/mmap.c	2010-01-22 17:15:08.000000000 -0700
+@@ -932,13 +932,9 @@ unsigned long do_mmap_pgoff(struct file 
+ 	if (!(flags & MAP_FIXED))
+ 		addr = round_hint_to_min(addr);
+ 
+-	error = arch_mmap_check(addr, len, flags);
+-	if (error)
+-		return error;
+-
+ 	/* Careful about overflows.. */
+ 	len = PAGE_ALIGN(len);
+-	if (!len || len > TASK_SIZE)
++	if (!len)
+ 		return -ENOMEM;
+ 
+ 	/* offset overflow? */
+@@ -1429,6 +1425,14 @@ get_unmapped_area(struct file *file, uns
+ 	unsigned long (*get_area)(struct file *, unsigned long,
+ 				  unsigned long, unsigned long, unsigned long);
+ 
++	unsigned long error = arch_mmap_check(addr, len, flags);
++	if (error)
++		return error;
++
++	/* Careful about overflows.. */
++	if (len > TASK_SIZE)
++		return -ENOMEM;
++
+ 	get_area = current->mm->get_unmapped_area;
+ 	if (file && file->f_op && file->f_op->get_unmapped_area)
+ 		get_area = file->f_op->get_unmapped_area;
+@@ -1956,20 +1960,14 @@ unsigned long do_brk(unsigned long addr,
+ 	if (!len)
+ 		return addr;
+ 
+-	if ((addr + len) > TASK_SIZE || (addr + len) < addr)
+-		return -EINVAL;
+-
+-	if (is_hugepage_only_range(mm, addr, len))
+-		return -EINVAL;
+-
+ 	error = security_file_mmap(NULL, 0, 0, 0, addr, 1);
+ 	if (error)
+ 		return error;
+ 
+ 	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
+ 
+-	error = arch_mmap_check(addr, len, flags);
+-	if (error)
++	error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED);
++	if (error & ~PAGE_MASK)
+ 		return error;
+ 
+ 	/*
+diff -urpN linux-source-2.6.26.orig/mm/mremap.c linux-source-2.6.26/mm/mremap.c
+--- linux-source-2.6.26.orig/mm/mremap.c	2009-12-26 01:14:56.000000000 -0700
++++ linux-source-2.6.26/mm/mremap.c	2010-01-22 17:15:08.000000000 -0700
+@@ -239,6 +239,137 @@ static unsigned long move_vma(struct vm_
+ 	return new_addr;
+ }
+ 
++static struct vm_area_struct *vma_to_resize(unsigned long addr,
++	unsigned long old_len, unsigned long new_len, unsigned long *p)
++{
++	struct mm_struct *mm = current->mm;
++	struct vm_area_struct *vma = find_vma(mm, addr);
++
++	if (!vma || vma->vm_start > addr)
++		goto Efault;
++
++	if (is_vm_hugetlb_page(vma))
++		goto Einval;
++
++	/* We can't remap across vm area boundaries */
++	if (old_len > vma->vm_end - addr)
++		goto Efault;
++
++	if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) {
++		if (new_len > old_len)
++			goto Efault;
++	}
++
++	if (vma->vm_flags & VM_LOCKED) {
++		unsigned long locked, lock_limit;
++		locked = mm->locked_vm << PAGE_SHIFT;
++		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
++		locked += new_len - old_len;
++		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
++			goto Eagain;
++	}
++
++	if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT))
++		goto Enomem;
++
++	if (vma->vm_flags & VM_ACCOUNT) {
++		unsigned long charged = (new_len - old_len) >> PAGE_SHIFT;
++		if (security_vm_enough_memory(charged))
++			goto Efault;
++		*p = charged;
++	}
++
++	return vma;
++
++Efault:	/* very odd choice for most of the cases, but... */
++	return ERR_PTR(-EFAULT);
++Einval:
++	return ERR_PTR(-EINVAL);
++Enomem:
++	return ERR_PTR(-ENOMEM);
++Eagain:
++	return ERR_PTR(-EAGAIN);
++}
++
++static unsigned long mremap_to(unsigned long addr,
++	unsigned long old_len, unsigned long new_addr,
++	unsigned long new_len)
++{
++	struct mm_struct *mm = current->mm;
++	struct vm_area_struct *vma;
++	unsigned long ret = -EINVAL;
++	unsigned long charged = 0;
++	unsigned long map_flags;
++
++	if (new_addr & ~PAGE_MASK)
++		goto out;
++
++	if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
++		goto out;
++
++	/* Check if the location we're moving into overlaps the
++	 * old location at all, and fail if it does.
++	 */
++	if ((new_addr <= addr) && (new_addr+new_len) > addr)
++		goto out;
++
++	if ((addr <= new_addr) && (addr+old_len) > new_addr)
++		goto out;
++
++	ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
++	if (ret)
++		goto out;
++
++	ret = do_munmap(mm, new_addr, new_len);
++	if (ret)
++		goto out;
++
++	if (old_len >= new_len) {
++		ret = do_munmap(mm, addr+new_len, old_len - new_len);
++		if (ret && old_len != new_len)
++			goto out;
++		old_len = new_len;
++	}
++
++	vma = vma_to_resize(addr, old_len, new_len, &charged);
++	if (IS_ERR(vma)) {
++		ret = PTR_ERR(vma);
++		goto out;
++	}
++
++	map_flags = MAP_FIXED;
++	if (vma->vm_flags & VM_MAYSHARE)
++		map_flags |= MAP_SHARED;
++
++	ret = get_unmapped_area(vma->vm_file, new_addr, new_len, vma->vm_pgoff +
++				((addr - vma->vm_start) >> PAGE_SHIFT),
++				map_flags);
++	if (ret & ~PAGE_MASK)
++		goto out1;
++
++	ret = move_vma(vma, addr, old_len, new_len, new_addr);
++	if (!(ret & ~PAGE_MASK))
++		goto out;
++out1:
++	vm_unacct_memory(charged);
++
++out:
++	return ret;
++}
++
++static int vma_expandable(struct vm_area_struct *vma, unsigned long delta)
++{
++	unsigned long end = vma->vm_end + delta;
++	if (end < vma->vm_end) /* overflow */
++		return 0;
++	if (vma->vm_next && vma->vm_next->vm_start < end) /* intersection */
++		return 0;
++	if (get_unmapped_area(NULL, vma->vm_start, end - vma->vm_start,
++			      0, MAP_FIXED) & ~PAGE_MASK)
++		return 0;
++	return 1;
++}
++
+ /*
+  * Expand (or shrink) an existing mapping, potentially moving it at the
+  * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
+@@ -272,32 +403,10 @@ unsigned long do_mremap(unsigned long ad
+ 	if (!new_len)
+ 		goto out;
+ 
+-	/* new_addr is only valid if MREMAP_FIXED is specified */
+ 	if (flags & MREMAP_FIXED) {
+-		if (new_addr & ~PAGE_MASK)
+-			goto out;
+-		if (!(flags & MREMAP_MAYMOVE))
+-			goto out;
+-
+-		if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
+-			goto out;
+-
+-		/* Check if the location we're moving into overlaps the
+-		 * old location at all, and fail if it does.
+-		 */
+-		if ((new_addr <= addr) && (new_addr+new_len) > addr)
+-			goto out;
+-
+-		if ((addr <= new_addr) && (addr+old_len) > new_addr)
+-			goto out;
+-
+-		ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
+-		if (ret)
+-			goto out;
+-
+-		ret = do_munmap(mm, new_addr, new_len);
+-		if (ret)
+-			goto out;
++		if (flags & MREMAP_MAYMOVE)
++			ret = mremap_to(addr, old_len, new_addr, new_len);
++		goto out;
+ 	}
+ 
+ 	/*
+@@ -310,60 +419,23 @@ unsigned long do_mremap(unsigned long ad
+ 		if (ret && old_len != new_len)
+ 			goto out;
+ 		ret = addr;
+-		if (!(flags & MREMAP_FIXED) || (new_addr == addr))
+-			goto out;
+-		old_len = new_len;
++		goto out;
+ 	}
+ 
+ 	/*
+-	 * Ok, we need to grow..  or relocate.
++	 * Ok, we need to grow..
+ 	 */
+-	ret = -EFAULT;
+-	vma = find_vma(mm, addr);
+-	if (!vma || vma->vm_start > addr)
++	vma = vma_to_resize(addr, old_len, new_len, &charged);
++	if (IS_ERR(vma)) {
++		ret = PTR_ERR(vma);
+ 		goto out;
+-	if (is_vm_hugetlb_page(vma)) {
+-		ret = -EINVAL;
+-		goto out;
+-	}
+-	/* We can't remap across vm area boundaries */
+-	if (old_len > vma->vm_end - addr)
+-		goto out;
+-	if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) {
+-		if (new_len > old_len)
+-			goto out;
+-	}
+-	if (vma->vm_flags & VM_LOCKED) {
+-		unsigned long locked, lock_limit;
+-		locked = mm->locked_vm << PAGE_SHIFT;
+-		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+-		locked += new_len - old_len;
+-		ret = -EAGAIN;
+-		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
+-			goto out;
+-	}
+-	if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) {
+-		ret = -ENOMEM;
+-		goto out;
+-	}
+-
+-	if (vma->vm_flags & VM_ACCOUNT) {
+-		charged = (new_len - old_len) >> PAGE_SHIFT;
+-		if (security_vm_enough_memory(charged))
+-			goto out_nc;
+ 	}
+ 
+ 	/* old_len exactly to the end of the area..
+-	 * And we're not relocating the area.
+ 	 */
+-	if (old_len == vma->vm_end - addr &&
+-	    !((flags & MREMAP_FIXED) && (addr != new_addr)) &&
+-	    (old_len != new_len || !(flags & MREMAP_MAYMOVE))) {
+-		unsigned long max_addr = TASK_SIZE;
+-		if (vma->vm_next)
+-			max_addr = vma->vm_next->vm_start;
++	if (old_len == vma->vm_end - addr) {
+ 		/* can we just expand the current mapping? */
+-		if (max_addr - addr >= new_len) {
++		if (vma_expandable(vma, new_len - old_len)) {
+ 			int pages = (new_len - old_len) >> PAGE_SHIFT;
+ 
+ 			vma_adjust(vma, vma->vm_start,
+@@ -387,28 +459,27 @@ unsigned long do_mremap(unsigned long ad
+ 	 */
+ 	ret = -ENOMEM;
+ 	if (flags & MREMAP_MAYMOVE) {
+-		if (!(flags & MREMAP_FIXED)) {
+-			unsigned long map_flags = 0;
+-			if (vma->vm_flags & VM_MAYSHARE)
+-				map_flags |= MAP_SHARED;
+-
+-			new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
+-						vma->vm_pgoff, map_flags);
+-			if (new_addr & ~PAGE_MASK) {
+-				ret = new_addr;
+-				goto out;
+-			}
+-
+-			ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
+-			if (ret)
+-				goto out;
++		unsigned long map_flags = 0;
++		if (vma->vm_flags & VM_MAYSHARE)
++			map_flags |= MAP_SHARED;
++
++		new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
++					vma->vm_pgoff +
++					((addr - vma->vm_start) >> PAGE_SHIFT),
++					map_flags);
++		if (new_addr & ~PAGE_MASK) {
++			ret = new_addr;
++			goto out;
+ 		}
++
++		ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
++		if (ret)
++			goto out;
+ 		ret = move_vma(vma, addr, old_len, new_len, new_addr);
+ 	}
+ out:
+ 	if (ret & ~PAGE_MASK)
+ 		vm_unacct_memory(charged);
+-out_nc:
+ 	return ret;
+ }
+ 
+diff -urpN linux-source-2.6.26.orig/mm/util.c linux-source-2.6.26/mm/util.c
+--- linux-source-2.6.26.orig/mm/util.c	2008-07-13 15:51:29.000000000 -0600
++++ linux-source-2.6.26/mm/util.c	2010-01-22 17:29:51.000000000 -0700
+@@ -2,6 +2,10 @@
+ #include <linux/string.h>
+ #include <linux/module.h>
+ #include <linux/err.h>
++#include <linux/hugetlb.h>
++#include <linux/syscalls.h>
++#include <linux/mman.h>
++#include <linux/file.h>
+ #include <asm/uaccess.h>
+ 
+ /**
+@@ -136,3 +140,30 @@ char *strndup_user(const char __user *s,
+ 	return p;
+ }
+ EXPORT_SYMBOL(strndup_user);
++
++SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
++		unsigned long, prot, unsigned long, flags,
++		unsigned long, fd, unsigned long, pgoff)
++{
++	struct file * file = NULL;
++	unsigned long retval = -EBADF;
++
++	if (!(flags & MAP_ANONYMOUS)) {
++		/*if (unlikely(flags & MAP_HUGETLB))
++			return -EINVAL;*/
++		file = fget(fd);
++		if (!file)
++			goto out;
++	}
++
++	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
++
++	down_write(&current->mm->mmap_sem);
++	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
++	up_write(&current->mm->mmap_sem);
++
++	if (file)
++		fput(file);
++out:
++	return retval;
++}

Modified: dists/lenny-security/linux-2.6/debian/patches/features/all/openvz/openvz.patch
==============================================================================
--- dists/lenny-security/linux-2.6/debian/patches/features/all/openvz/openvz.patch	Wed Jan 27 16:35:55 2010	(r15043)
+++ dists/lenny-security/linux-2.6/debian/patches/features/all/openvz/openvz.patch	Wed Jan 27 16:52:30 2010	(r15044)
@@ -996,19 +996,6 @@
  			}
  		}
  	}
-diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
-index 1eda194..e93e7d3 100644
---- a/arch/ia64/kernel/sys_ia64.c
-+++ b/arch/ia64/kernel/sys_ia64.c
-@@ -204,7 +204,7 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un
- 
- 	/* Careful about overflows.. */
- 	len = PAGE_ALIGN(len);
--	if (!len || len > TASK_SIZE) {
-+	if (len > TASK_SIZE) {
- 		addr = -EINVAL;
- 		goto out;
- 	}
 diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
 index aad1b7b..9194bf5 100644
 --- a/arch/ia64/kernel/time.c
@@ -30496,8 +30483,8 @@
  	else
  		user_shm_unlock(shp->shm_file->f_path.dentry->d_inode->i_size,
  						shp->mlock_user);
-@@ -319,12 +337,13 @@ int is_file_shm_hugepages(struct file *file)
- 	return ret;
+@@ -308,11 +326,12 @@ static unsigned long shm_get_unmapped_ar
+ 						pgoff, flags);
  }
  
 -static const struct file_operations shm_file_operations = {
@@ -30505,12 +30492,11 @@
  	.mmap		= shm_mmap,
  	.fsync		= shm_fsync,
  	.release	= shm_release,
- 	.get_unmapped_area	= shm_get_unmapped_area,
  };
 +EXPORT_SYMBOL_GPL(shm_file_operations);
  
- static struct vm_operations_struct shm_vm_ops = {
- 	.open	= shm_open,	/* callback for a new vm-area open */
+ static const struct file_operations shm_file_operations_huge = {
+ 	.mmap		= shm_mmap,
 @@ -349,11 +368,12 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
  	key_t key = params->key;
  	int shmflg = params->flg;
@@ -67782,10 +67768,10 @@
  }
  
  /*
-@@ -364,7 +376,15 @@ unsigned long do_mremap(unsigned long addr,
- 			max_addr = vma->vm_next->vm_start;
+@@ -436,7 +448,15 @@ unsigned long do_mremap(unsigned long ad
+ 	if (old_len == vma->vm_end - addr) {
  		/* can we just expand the current mapping? */
- 		if (max_addr - addr >= new_len) {
+ 		if (vma_expandable(vma, new_len - old_len)) {
 -			int pages = (new_len - old_len) >> PAGE_SHIFT;
 +			unsigned long len;
 +			int pages;

Modified: dists/lenny-security/linux-2.6/debian/patches/features/all/vserver/vs2.3.0.35.patch
==============================================================================
--- dists/lenny-security/linux-2.6/debian/patches/features/all/vserver/vs2.3.0.35.patch	Wed Jan 27 16:35:55 2010	(r15043)
+++ dists/lenny-security/linux-2.6/debian/patches/features/all/vserver/vs2.3.0.35.patch	Wed Jan 27 16:52:30 2010	(r15044)
@@ -26003,16 +26003,16 @@
  		if (new_len > old_len)
  			make_pages_present(new_addr + old_len,
  					   new_addr + new_len);
-@@ -341,6 +342,9 @@ unsigned long do_mremap(unsigned long ad
- 		ret = -EAGAIN;
+@@ -267,6 +268,9 @@ static struct vm_area_struct *vma_to_res
+ 		locked += new_len - old_len;
  		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
- 			goto out;
+ 			goto Eagain;
 +		if (!vx_vmlocked_avail(current->mm,
 +			(new_len - old_len) >> PAGE_SHIFT))
-+			goto out;
++			goto Einval;
  	}
- 	if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) {
- 		ret = -ENOMEM;
+ 
+ 	if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT))
 @@ -369,10 +373,10 @@ unsigned long do_mremap(unsigned long ad
  			vma_adjust(vma, vma->vm_start,
  				addr + new_len, vma->vm_pgoff, NULL);

Modified: dists/lenny-security/linux-2.6/debian/patches/series/21lenny1
==============================================================================
--- dists/lenny-security/linux-2.6/debian/patches/series/21lenny1	Wed Jan 27 16:35:55 2010	(r15043)
+++ dists/lenny-security/linux-2.6/debian/patches/series/21lenny1	Wed Jan 27 16:52:30 2010	(r15044)
@@ -3,3 +3,4 @@
 + bugfix/all/netfilter-ebtables-enforce-CAP_NET_ADMIN.patch
 + bugfix/all/e1000-enhance-frame-fragment-detection.patch
 + bugfix/all/e1000e-enhance-frame-fragment-detection.patch
++ bugfix/all/untangle-the-do_mremap-mess.patch



More information about the Kernel-svn-changes mailing list