Commit aad3bf04 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/viro/mmap

* git://git.kernel.org/pub/scm/linux/kernel/git/viro/mmap:
  Add missing alignment check in arch/score sys_mmap()
  fix broken aliasing checks for MAP_FIXED on sparc32, mips, arm and sh
  Get rid of open-coding in ia64_brk()
  sparc_brk() is not needed anymore
  switch do_brk() to get_unmapped_area()
  Take arch_mmap_check() into get_unmapped_area()
  fix a struct file leak in do_mmap_pgoff()
  Unify sys_mmap*
  Cut hugetlb case early for 32bit on ia64
  arch_mmap_check() on mn10300
  Kill ancient crap in s390 compat mmap
  arm: add arch_mmap_check(), get rid of sys_arm_mremap()
  file ->get_unmapped_area() shouldn't duplicate work of get_unmapped_area()
  kill useless checks in sparc mremap variants
  fix pgoff in "have to relocate" case of mremap()
  fix the arch checks in MREMAP_FIXED case
  fix checks for expand-in-place mremap
  do_mremap() untangling, part 3
  do_mremap() untangling, part 2
  untangling do_mremap(), part 1
parents 11bd04f6 aa656073
...@@ -178,25 +178,18 @@ SYSCALL_DEFINE6(osf_mmap, unsigned long, addr, unsigned long, len, ...@@ -178,25 +178,18 @@ SYSCALL_DEFINE6(osf_mmap, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, prot, unsigned long, flags, unsigned long, fd,
unsigned long, off) unsigned long, off)
{ {
struct file *file = NULL; unsigned long ret = -EINVAL;
unsigned long ret = -EBADF;
#if 0 #if 0
if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED)) if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
printk("%s: unimplemented OSF mmap flags %04lx\n", printk("%s: unimplemented OSF mmap flags %04lx\n",
current->comm, flags); current->comm, flags);
#endif #endif
if (!(flags & MAP_ANONYMOUS)) { if ((off + PAGE_ALIGN(len)) < off)
file = fget(fd);
if (!file)
goto out; goto out;
} if (off & ~PAGE_MASK)
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); goto out;
down_write(&current->mm->mmap_sem); ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
ret = do_mmap(file, addr, len, prot, flags, off);
up_write(&current->mm->mmap_sem);
if (file)
fput(file);
out: out:
return ret; return ret;
} }
......
#include <asm-generic/mman.h> #include <asm-generic/mman.h>
#define arch_mmap_check(addr, len, flags) \
(((flags) & MAP_FIXED && (addr) < FIRST_USER_ADDRESS) ? -EINVAL : 0)
...@@ -172,7 +172,7 @@ ...@@ -172,7 +172,7 @@
/* 160 */ CALL(sys_sched_get_priority_min) /* 160 */ CALL(sys_sched_get_priority_min)
CALL(sys_sched_rr_get_interval) CALL(sys_sched_rr_get_interval)
CALL(sys_nanosleep) CALL(sys_nanosleep)
CALL(sys_arm_mremap) CALL(sys_mremap)
CALL(sys_setresuid16) CALL(sys_setresuid16)
/* 165 */ CALL(sys_getresuid16) /* 165 */ CALL(sys_getresuid16)
CALL(sys_ni_syscall) /* vm86 */ CALL(sys_ni_syscall) /* vm86 */
......
...@@ -416,12 +416,12 @@ sys_mmap2: ...@@ -416,12 +416,12 @@ sys_mmap2:
tst r5, #PGOFF_MASK tst r5, #PGOFF_MASK
moveq r5, r5, lsr #PAGE_SHIFT - 12 moveq r5, r5, lsr #PAGE_SHIFT - 12
streq r5, [sp, #4] streq r5, [sp, #4]
beq do_mmap2 beq sys_mmap_pgoff
mov r0, #-EINVAL mov r0, #-EINVAL
mov pc, lr mov pc, lr
#else #else
str r5, [sp, #4] str r5, [sp, #4]
b do_mmap2 b sys_mmap_pgoff
#endif #endif
ENDPROC(sys_mmap2) ENDPROC(sys_mmap2)
......
...@@ -28,41 +28,6 @@ ...@@ -28,41 +28,6 @@
#include <linux/ipc.h> #include <linux/ipc.h>
#include <linux/uaccess.h> #include <linux/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 { struct mmap_arg_struct {
unsigned long addr; unsigned long addr;
unsigned long len; unsigned long len;
...@@ -84,29 +49,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) ...@@ -84,29 +49,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
if (a.offset & ~PAGE_MASK) if (a.offset & ~PAGE_MASK)
goto out; 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: out:
return error; 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 * Perform the select(nd, in, out, ex, tv) and mmap() system
* calls. * calls.
......
...@@ -54,7 +54,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, ...@@ -54,7 +54,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
* We enforce the MAP_FIXED case. * We enforce the MAP_FIXED case.
*/ */
if (flags & MAP_FIXED) { 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 -EINVAL;
return addr; return addr;
} }
......
...@@ -29,10 +29,6 @@ asmlinkage int sys_sigaltstack(const stack_t __user *, stack_t __user *, ...@@ -29,10 +29,6 @@ asmlinkage int sys_sigaltstack(const stack_t __user *, stack_t __user *,
struct pt_regs *); struct pt_regs *);
asmlinkage int sys_rt_sigreturn(struct pt_regs *); asmlinkage int sys_rt_sigreturn(struct pt_regs *);
/* kernel/sys_avr32.c */
asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, off_t);
/* mm/cache.c */ /* mm/cache.c */
asmlinkage int sys_cacheflush(int, void __user *, size_t); asmlinkage int sys_cacheflush(int, void __user *, size_t);
......
...@@ -5,39 +5,8 @@ ...@@ -5,39 +5,8 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * 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 <linux/unistd.h>
#include <asm/mman.h>
#include <asm/uaccess.h>
#include <asm/syscalls.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) int kernel_execve(const char *file, char **argv, char **envp)
{ {
register long scno asm("r8") = __NR_execve; register long scno asm("r8") = __NR_execve;
......
...@@ -61,7 +61,7 @@ __sys_execve: ...@@ -61,7 +61,7 @@ __sys_execve:
__sys_mmap2: __sys_mmap2:
pushm lr pushm lr
st.w --sp, ARG6 st.w --sp, ARG6
call sys_mmap2 call sys_mmap_pgoff
sub sp, -4 sub sp, -4
popm pc popm pc
......
...@@ -22,39 +22,6 @@ ...@@ -22,39 +22,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/dma.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 void *sys_sram_alloc(size_t size, unsigned long flags) asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags)
{ {
return sram_alloc_with_lsl(size, flags); return sram_alloc_with_lsl(size, flags);
......
...@@ -1422,7 +1422,7 @@ ENTRY(_sys_call_table) ...@@ -1422,7 +1422,7 @@ ENTRY(_sys_call_table)
.long _sys_ni_syscall /* streams2 */ .long _sys_ni_syscall /* streams2 */
.long _sys_vfork /* 190 */ .long _sys_vfork /* 190 */
.long _sys_getrlimit .long _sys_getrlimit
.long _sys_mmap2 .long _sys_mmap_pgoff
.long _sys_truncate64 .long _sys_truncate64
.long _sys_ftruncate64 .long _sys_ftruncate64
.long _sys_stat64 /* 195 */ .long _sys_stat64 /* 195 */
......
...@@ -26,31 +26,6 @@ ...@@ -26,31 +26,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/segment.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) asmlinkage unsigned long old_mmap(unsigned long __user *args)
{ {
unsigned long buffer[6]; unsigned long buffer[6];
...@@ -63,7 +38,7 @@ asmlinkage unsigned long old_mmap(unsigned long __user *args) ...@@ -63,7 +38,7 @@ asmlinkage unsigned long old_mmap(unsigned long __user *args)
if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */ if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */
goto out; 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); buffer[4], buffer[5] >> PAGE_SHIFT);
out: out:
return err; return err;
...@@ -73,7 +48,8 @@ asmlinkage long ...@@ -73,7 +48,8 @@ asmlinkage long
sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
unsigned long flags, unsigned long fd, unsigned long pgoff) 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);
} }
/* /*
......
...@@ -31,9 +31,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, ...@@ -31,9 +31,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff) unsigned long fd, unsigned long pgoff)
{ {
int error = -EBADF;
struct file * file = NULL;
/* As with sparc32, make sure the shift for mmap2 is constant /* As with sparc32, make sure the shift for mmap2 is constant
(12), no matter what PAGE_SIZE we have.... */ (12), no matter what PAGE_SIZE we have.... */
...@@ -41,69 +38,10 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, ...@@ -41,69 +38,10 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
trying to map something we can't */ trying to map something we can't */
if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1)) if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
return -EINVAL; return -EINVAL;
pgoff >>= PAGE_SHIFT - 12;
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;
}
#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); return sys_mmap_pgoff(addr, len, prot, flags, fd,
error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); pgoff >> (PAGE_SHIFT - 12));
up_write(&current->mm->mmap_sem);
if (file)
fput(file);
out:
return error;
} }
#endif
/* /*
* sys_ipc() is the de-multiplexer for the SysV IPC calls.. * sys_ipc() is the de-multiplexer for the SysV IPC calls..
......
...@@ -26,39 +26,6 @@ ...@@ -26,39 +26,6 @@
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/unistd.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 * 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 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
...@@ -87,57 +54,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) ...@@ -87,57 +54,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg)
if (a.offset & ~PAGE_MASK) if (a.offset & ~PAGE_MASK)
goto out; goto out;
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
a.offset >> PAGE_SHIFT);
error = do_mmap2(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: out:
return error; return error;
} }
#endif
struct sel_arg_struct { struct sel_arg_struct {
unsigned long n; unsigned long n;
......
...@@ -206,7 +206,7 @@ SYMBOL_NAME_LABEL(sys_call_table) ...@@ -206,7 +206,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */ .long SYMBOL_NAME(sys_vfork) /* 190 */
.long SYMBOL_NAME(sys_getrlimit) .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_truncate64)
.long SYMBOL_NAME(sys_ftruncate64) .long SYMBOL_NAME(sys_ftruncate64)
.long SYMBOL_NAME(sys_stat64) /* 195 */ .long SYMBOL_NAME(sys_stat64) /* 195 */
......
...@@ -858,6 +858,9 @@ ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot ...@@ -858,6 +858,9 @@ ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot
prot = get_prot32(prot); prot = get_prot32(prot);
if (flags & MAP_HUGETLB)
return -ENOMEM;
#if PAGE_SHIFT > IA32_PAGE_SHIFT #if PAGE_SHIFT > IA32_PAGE_SHIFT
mutex_lock(&ia32_mmap_mutex); mutex_lock(&ia32_mmap_mutex);
{ {
......
...@@ -100,51 +100,7 @@ sys_getpagesize (void) ...@@ -100,51 +100,7 @@ sys_getpagesize (void)
asmlinkage unsigned long asmlinkage unsigned long
ia64_brk (unsigned long brk) ia64_brk (unsigned long brk)
{ {
unsigned long rlim, retval, newbrk, oldbrk; unsigned long retval = sys_brk(brk);
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);
force_successful_syscall_return(); force_successful_syscall_return();
return retval; return retval;
} }
...@@ -185,39 +141,6 @@ int ia64_mmap_check(unsigned long addr, unsigned long len, ...@@ -185,39 +141,6 @@ int ia64_mmap_check(unsigned long addr, unsigned long len,
return 0; 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 * mmap2() is like mmap() except that the offset is expressed in units
* of PAGE_SIZE (instead of bytes). This allows to mmap2() (pieces * of PAGE_SIZE (instead of bytes). This allows to mmap2() (pieces
...@@ -226,7 +149,7 @@ out: if (file) ...@@ -226,7 +149,7 @@ out: if (file)
asmlinkage unsigned long asmlinkage unsigned long
sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff) 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)) if (!IS_ERR((void *) addr))
force_successful_syscall_return(); force_successful_syscall_return();
return addr; return addr;
...@@ -238,7 +161,7 @@ sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, lo ...@@ -238,7 +161,7 @@ sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, lo
if (offset_in_page(off) != 0) if (offset_in_page(off) != 0)
return -EINVAL; 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)) if (!IS_ERR((void *) addr))
force_successful_syscall_return(); force_successful_syscall_return();
return addr; return addr;
......
...@@ -76,30 +76,6 @@ asmlinkage int sys_tas(int __user *addr) ...@@ -76,30 +76,6 @@ asmlinkage int sys_tas(int __user *addr)
return oldval; 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.. * sys_ipc() is the de-multiplexer for the SysV IPC calls..
* *
......
...@@ -191,7 +191,7 @@ ENTRY(sys_call_table) ...@@ -191,7 +191,7 @@ ENTRY(sys_call_table)
.long sys_ni_syscall /* streams2 */ .long sys_ni_syscall /* streams2 */
.long sys_vfork /* 190 */ .long sys_vfork /* 190 */
.long sys_getrlimit .long sys_getrlimit
.long sys_mmap2 .long sys_mmap_pgoff
.long sys_truncate64 .long sys_truncate64
.long sys_ftruncate64 .long sys_ftruncate64
.long sys_stat64 /* 195 */ .long sys_stat64 /* 195 */
......
...@@ -29,37 +29,16 @@ ...@@ -29,37 +29,16 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/unistd.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, asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff) 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);
} }
/* /*
...@@ -90,57 +69,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) ...@@ -90,57 +69,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
if (a.offset & ~PAGE_MASK) if (a.offset & ~PAGE_MASK)
goto out; goto out;
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
a.offset >> PAGE_SHIFT);
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);
out: out:
return error; return error;
} }
#endif
struct sel_arg_struct { struct sel_arg_struct {
unsigned long n; unsigned long n;
......
...@@ -27,39 +27,6 @@ ...@@ -27,39 +27,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/unistd.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 * 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 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
...@@ -88,9 +55,8 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) ...@@ -88,9 +55,8 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg)
if (a.offset & ~PAGE_MASK) if (a.offset & ~PAGE_MASK)
goto out; goto out;
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
a.offset >> PAGE_SHIFT);
error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
out: out:
return error; return error;
} }
......
...@@ -210,7 +210,7 @@ ENTRY(sys_call_table) ...@@ -210,7 +210,7 @@ ENTRY(sys_call_table)
.long sys_ni_syscall /* streams2 */ .long sys_ni_syscall /* streams2 */
.long sys_vfork /* 190 */ .long sys_vfork /* 190 */
.long sys_getrlimit .long sys_getrlimit
.long sys_mmap2 .long sys_mmap_pgoff
.long sys_truncate64 .long sys_truncate64
.long sys_ftruncate64 .long sys_ftruncate64
.long sys_stat64 /* 195 */ .long sys_stat64 /* 195 */
......
...@@ -62,46 +62,14 @@ asmlinkage long microblaze_execve(char __user *filenamei, char __user *__user *a ...@@ -62,46 +62,14 @@ asmlinkage long microblaze_execve(char __user *filenamei, char __user *__user *a
return error; return error;
} }
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;
int ret = -EBADF;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file) {
printk(KERN_INFO "no fd in mmap\r\n");
goto out;
}
}
down_write(&current->mm->mmap_sem);
ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up_write(&current->mm->mmap_sem);
if (file)
fput(file);
out:
return ret;
}
asmlinkage long sys_mmap(unsigned long addr, unsigned long len, asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
unsigned long fd, off_t pgoff) unsigned long fd, off_t pgoff)
{ {
int err = -EINVAL; if (pgoff & ~PAGE_MASK)
return -EINVAL;
if (pgoff & ~PAGE_MASK) { return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
printk(KERN_INFO "no pagemask in mmap\r\n");
goto out;
}
err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
out:
return err;
} }
/* /*
......
...@@ -196,7 +196,7 @@ ENTRY(sys_call_table) ...@@ -196,7 +196,7 @@ ENTRY(sys_call_table)
.long sys_ni_syscall /* reserved for streams2 */ .long sys_ni_syscall /* reserved for streams2 */
.long sys_vfork /* 190 */ .long sys_vfork /* 190 */
.long sys_getrlimit .long sys_getrlimit
.long sys_mmap2 /* mmap2 */ .long sys_mmap_pgoff /* mmap2 */
.long sys_truncate64 .long sys_truncate64
.long sys_ftruncate64 .long sys_ftruncate64
.long sys_stat64 /* 195 */ .long sys_stat64 /* 195 */
......
...@@ -67,28 +67,13 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len, ...@@ -67,28 +67,13 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, prot, unsigned long, flags, unsigned long, fd,
unsigned long, pgoff) unsigned long, pgoff)
{ {
struct file * file = NULL;
unsigned long error; unsigned long error;
error = -EINVAL; error = -EINVAL;
if (pgoff & (~PAGE_MASK >> 12)) if (pgoff & (~PAGE_MASK >> 12))
goto out; goto out;
pgoff >>= PAGE_SHIFT-12; error = sys_mmap_pgoff(addr, len, prot, flags, fd,
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);
out: out:
return error; return error;
} }
......
...@@ -93,7 +93,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, ...@@ -93,7 +93,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
* We do not accept a shared mapping if it would violate * We do not accept a shared mapping if it would violate
* cache aliasing constraints. * 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 -EINVAL;
return addr; return addr;
} }
...@@ -129,31 +130,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, ...@@ -129,31 +130,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
} }
} }
/* 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, SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags, unsigned long, unsigned long, prot, unsigned long, flags, unsigned long,
fd, off_t, offset) fd, off_t, offset)
...@@ -164,7 +140,7 @@ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, ...@@ -164,7 +140,7 @@ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
if (offset & ~PAGE_MASK) if (offset & ~PAGE_MASK)
goto out; 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: out:
return result; return result;
...@@ -177,7 +153,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len, ...@@ -177,7 +153,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
if (pgoff & (~PAGE_MASK >> 12)) if (pgoff & (~PAGE_MASK >> 12))
return -EINVAL; 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); save_static_function(sys_fork);
......
#include <asm-generic/mman.h> #include <asm-generic/mman.h>
#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)
...@@ -578,7 +578,7 @@ ENTRY(sys_call_table) ...@@ -578,7 +578,7 @@ ENTRY(sys_call_table)
.long sys_ni_syscall /* reserved for streams2 */ .long sys_ni_syscall /* reserved for streams2 */
.long sys_vfork /* 190 */ .long sys_vfork /* 190 */
.long sys_getrlimit .long sys_getrlimit
.long sys_mmap2 .long sys_mmap_pgoff
.long sys_truncate64 .long sys_truncate64
.long sys_ftruncate64 .long sys_ftruncate64
.long sys_stat64 /* 195 */ .long sys_stat64 /* 195 */
......
...@@ -23,47 +23,13 @@ ...@@ -23,47 +23,13 @@
#include <asm/uaccess.h> #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, asmlinkage long old_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long offset) unsigned long fd, unsigned long offset)
{ {
if (offset & ~PAGE_MASK) if (offset & ~PAGE_MASK)
return -EINVAL; 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 { struct sel_arg_struct {
......
...@@ -110,37 +110,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, ...@@ -110,37 +110,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
return addr; 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, asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long fd, unsigned long prot, unsigned long flags, unsigned long fd,
unsigned long pgoff) unsigned long pgoff)
{ {
/* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
we have. */ 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, asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
...@@ -148,7 +125,8 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, ...@@ -148,7 +125,8 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
unsigned long offset) unsigned long offset)
{ {
if (!(offset & ~PAGE_MASK)) { 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 { } else {
return -EINVAL; return -EINVAL;
} }
......
...@@ -140,7 +140,6 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len, ...@@ -140,7 +140,6 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long off, int shift) unsigned long fd, unsigned long off, int shift)
{ {
struct file * file = NULL;
unsigned long ret = -EINVAL; unsigned long ret = -EINVAL;
if (!arch_validate_prot(prot)) if (!arch_validate_prot(prot))
...@@ -152,19 +151,7 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len, ...@@ -152,19 +151,7 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len,
off >>= shift; off >>= shift;
} }
ret = -EBADF; ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off);
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);
out: out:
return ret; return ret;
} }
......
...@@ -624,38 +624,6 @@ struct mmap_arg_struct_emu31 { ...@@ -624,38 +624,6 @@ struct mmap_arg_struct_emu31 {
u32 offset; 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 asmlinkage unsigned long
old32_mmap(struct mmap_arg_struct_emu31 __user *arg) old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
{ {
...@@ -669,7 +637,8 @@ old32_mmap(struct mmap_arg_struct_emu31 __user *arg) ...@@ -669,7 +637,8 @@ old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
if (a.offset & ~PAGE_MASK) if (a.offset & ~PAGE_MASK)
goto out; 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: out:
return error; return error;
} }
...@@ -682,7 +651,7 @@ sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) ...@@ -682,7 +651,7 @@ sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
if (copy_from_user(&a, arg, sizeof(a))) if (copy_from_user(&a, arg, sizeof(a)))
goto out; 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: out:
return error; return error;
} }
......
...@@ -32,32 +32,6 @@ ...@@ -32,32 +32,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "entry.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 * Perform the select(nd, in, out, ex, tv) and mmap() system
* calls. Linux for S/390 isn't able to handle more than 5 * calls. Linux for S/390 isn't able to handle more than 5
...@@ -81,7 +55,7 @@ SYSCALL_DEFINE1(mmap2, struct mmap_arg_struct __user *, arg) ...@@ -81,7 +55,7 @@ SYSCALL_DEFINE1(mmap2, struct mmap_arg_struct __user *, arg)
if (copy_from_user(&a, arg, sizeof(a))) if (copy_from_user(&a, arg, sizeof(a)))
goto out; 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: out:
return error; return error;
} }
...@@ -98,7 +72,7 @@ SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct __user *, arg) ...@@ -98,7 +72,7 @@ SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct __user *, arg)
if (a.offset & ~PAGE_MASK) if (a.offset & ~PAGE_MASK)
goto out; 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: out:
return error; return error;
} }
......
...@@ -36,34 +36,16 @@ asmlinkage long ...@@ -36,34 +36,16 @@ asmlinkage long
sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
unsigned long flags, unsigned long fd, unsigned long pgoff) unsigned long flags, unsigned long fd, unsigned long pgoff)
{ {
int error = -EBADF; return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
struct file *file = NULL;
if (pgoff & (~PAGE_MASK >> 12))
return -EINVAL;
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, pgoff);
up_write(&current->mm->mmap_sem);
if (file)
fput(file);
return error;
} }
asmlinkage long asmlinkage long
sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, sys_mmap(unsigned long addr, unsigned long len, unsigned long prot,
unsigned long flags, unsigned long fd, off_t pgoff) unsigned long flags, unsigned long fd, off_t offset)
{ {
return sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); if (unlikely(offset & ~PAGE_MASK))
return -EINVAL;
return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
} }
asmlinkage long asmlinkage long
......
...@@ -28,37 +28,13 @@ ...@@ -28,37 +28,13 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/cachectl.h> #include <asm/cachectl.h>
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, asmlinkage int old_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
int fd, unsigned long off) int fd, unsigned long off)
{ {
if (off & ~PAGE_MASK) if (off & ~PAGE_MASK)
return -EINVAL; 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, asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
...@@ -74,7 +50,7 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, ...@@ -74,7 +50,7 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
pgoff >>= PAGE_SHIFT - 12; pgoff >>= PAGE_SHIFT - 12;
return do_mmap2(addr, len, prot, flags, fd, pgoff); return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
} }
/* /*
......
...@@ -54,7 +54,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, ...@@ -54,7 +54,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
/* We do not accept a shared mapping if it would violate /* We do not accept a shared mapping if it would violate
* cache aliasing constraints. * 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 -EINVAL;
return addr; return addr;
} }
......
...@@ -564,28 +564,6 @@ asmlinkage long sparc32_open(const char __user *filename, ...@@ -564,28 +564,6 @@ asmlinkage long sparc32_open(const char __user *filename,
return do_sys_open(AT_FDCWD, filename, flags, mode); return do_sys_open(AT_FDCWD, filename, flags, mode);
} }
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 sys32_mremap(unsigned long addr,
unsigned long old_len, unsigned long new_len,
unsigned long flags, u32 __new_addr)
{
unsigned long ret = -EINVAL;
unsigned long new_addr = __new_addr;
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;
}
long sys32_lookup_dcookie(unsigned long cookie_high, long sys32_lookup_dcookie(unsigned long cookie_high,
unsigned long cookie_low, unsigned long cookie_low,
char __user *buf, size_t len) char __user *buf, size_t len)
......
...@@ -45,7 +45,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi ...@@ -45,7 +45,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
/* We do not accept a shared mapping if it would violate /* We do not accept a shared mapping if it would violate
* cache aliasing constraints. * cache aliasing constraints.
*/ */
if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1))) if ((flags & MAP_SHARED) &&
((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
return -EINVAL; return -EINVAL;
return addr; return addr;
} }
...@@ -79,15 +80,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi ...@@ -79,15 +80,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
} }
} }
asmlinkage unsigned long sparc_brk(unsigned long brk)
{
if(ARCH_SUN4C) {
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 * sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though. * a pipe. It's not the way unix traditionally does this, though.
...@@ -234,31 +226,6 @@ int sparc_mmap_check(unsigned long addr, unsigned long len) ...@@ -234,31 +226,6 @@ int sparc_mmap_check(unsigned long addr, unsigned long len)
} }
/* Linux version of mmap */ /* 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, asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long fd, unsigned long prot, unsigned long flags, unsigned long fd,
...@@ -266,14 +233,16 @@ asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, ...@@ -266,14 +233,16 @@ asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
{ {
/* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
we have. */ 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, asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long fd, unsigned long prot, unsigned long flags, unsigned long fd,
unsigned long off) 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, long sparc_remap_file_pages(unsigned long start, unsigned long size,
...@@ -287,27 +256,6 @@ long sparc_remap_file_pages(unsigned long start, unsigned long size, ...@@ -287,27 +256,6 @@ long sparc_remap_file_pages(unsigned long start, unsigned long size,
(pgoff >> (PAGE_SHIFT - 12)), flags); (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 */ /* we come to here via sys_nis_syscall so it can setup the regs argument */
asmlinkage unsigned long asmlinkage unsigned long
c_sys_nis_syscall (struct pt_regs *regs) c_sys_nis_syscall (struct pt_regs *regs)
......
...@@ -317,10 +317,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, ...@@ -317,10 +317,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags) 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 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) { if (flags & MAP_FIXED) {
/* Ok, don't mess with it. */ /* 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; flags &= ~MAP_SHARED;
...@@ -333,7 +337,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u ...@@ -333,7 +337,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u
align_goal = (64UL * 1024); align_goal = (64UL * 1024);
do { 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)) { if (!(addr & ~PAGE_MASK)) {
addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL); addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL);
break; break;
...@@ -351,7 +355,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u ...@@ -351,7 +355,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u
* be obtained. * be obtained.
*/ */
if (addr & ~PAGE_MASK) 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; return addr;
} }
...@@ -399,18 +403,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm) ...@@ -399,18 +403,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
} }
} }
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 * sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though. * a pipe. It's not the way unix traditionally does this, though.
...@@ -568,23 +560,13 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, ...@@ -568,23 +560,13 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, prot, unsigned long, flags, unsigned long, fd,
unsigned long, off) unsigned long, off)
{ {
struct file * file = NULL; unsigned long retval = -EINVAL;
unsigned long retval = -EBADF;
if (!(flags & MAP_ANONYMOUS)) { if ((off + PAGE_ALIGN(len)) < off)
file = fget(fd);
if (!file)
goto out; goto out;
} if (off & ~PAGE_MASK)
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); goto out;
len = PAGE_ALIGN(len); retval = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
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);
out: out:
return retval; return retval;
} }
...@@ -614,12 +596,6 @@ SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len, ...@@ -614,12 +596,6 @@ SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len,
if (test_thread_flag(TIF_32BIT)) if (test_thread_flag(TIF_32BIT))
goto out; goto out;
if (unlikely(new_len >= VA_EXCLUDE_START))
goto out;
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); down_write(&current->mm->mmap_sem);
ret = do_mremap(addr, old_len, new_len, flags, new_addr); ret = do_mremap(addr, old_len, new_len, flags, new_addr);
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
struct new_utsname; struct new_utsname;
extern asmlinkage unsigned long sys_getpagesize(void); 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 sparc_pipe(struct pt_regs *regs);
extern asmlinkage long sys_ipc(unsigned int call, int first, extern asmlinkage long sys_ipc(unsigned int call, int first,
unsigned long second, unsigned long second,
......
...@@ -19,7 +19,7 @@ sys_call_table: ...@@ -19,7 +19,7 @@ sys_call_table:
/*0*/ .long sys_restart_syscall, sys_exit, sys_fork, sys_read, sys_write /*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 /*5*/ .long sys_open, sys_close, sys_wait4, sys_creat, sys_link
/*10*/ .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod /*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 /*20*/ .long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
/*25*/ .long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause /*25*/ .long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
/*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice /*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
...@@ -67,7 +67,7 @@ sys_call_table: ...@@ -67,7 +67,7 @@ sys_call_table:
/*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*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 /*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 /*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 /*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 /*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 /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
......
...@@ -21,7 +21,7 @@ sys_call_table32: ...@@ -21,7 +21,7 @@ sys_call_table32:
/*0*/ .word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write /*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 /*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod
/*15*/ .word sys_chmod, sys_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, sys_setuid16, sys_getuid16 /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause
/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
...@@ -68,7 +68,7 @@ sys_call_table32: ...@@ -68,7 +68,7 @@ sys_call_table32:
.word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler /*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
.word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
/*250*/ .word sys32_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl /*250*/ .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
.word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
...@@ -96,7 +96,7 @@ sys_call_table: ...@@ -96,7 +96,7 @@ sys_call_table:
/*0*/ .word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write /*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 /*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 /*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 /*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 /*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 /*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "linux/mm.h" #include "linux/mm.h"
#include "linux/sched.h" #include "linux/sched.h"
#include "linux/utsname.h" #include "linux/utsname.h"
#include "linux/syscalls.h"
#include "asm/current.h" #include "asm/current.h"
#include "asm/mman.h" #include "asm/mman.h"
#include "asm/uaccess.h" #include "asm/uaccess.h"
...@@ -37,31 +38,6 @@ long sys_vfork(void) ...@@ -37,31 +38,6 @@ long sys_vfork(void)
return ret; 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, long old_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long offset) unsigned long fd, unsigned long offset)
...@@ -70,7 +46,7 @@ long old_mmap(unsigned long addr, unsigned long len, ...@@ -70,7 +46,7 @@ long old_mmap(unsigned long addr, unsigned long len,
if (offset & ~PAGE_MASK) if (offset & ~PAGE_MASK)
goto out; 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: out:
return err; return err;
} }
......
...@@ -20,7 +20,3 @@ extern syscall_handler_t *sys_call_table[]; ...@@ -20,7 +20,3 @@ extern syscall_handler_t *sys_call_table[];
#define EXECUTE_SYSCALL(syscall, regs) \ #define EXECUTE_SYSCALL(syscall, regs) \
((long (*)(struct syscall_args)) \ ((long (*)(struct syscall_args)) \
(*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs)) (*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);
...@@ -696,7 +696,7 @@ ia32_sys_call_table: ...@@ -696,7 +696,7 @@ ia32_sys_call_table:
.quad quiet_ni_syscall /* streams2 */ .quad quiet_ni_syscall /* streams2 */
.quad stub32_vfork /* 190 */ .quad stub32_vfork /* 190 */
.quad compat_sys_getrlimit .quad compat_sys_getrlimit
.quad sys32_mmap2 .quad sys_mmap_pgoff
.quad sys32_truncate64 .quad sys32_truncate64
.quad sys32_ftruncate64 .quad sys32_ftruncate64
.quad sys32_stat64 /* 195 */ .quad sys32_stat64 /* 195 */
......
...@@ -155,9 +155,6 @@ struct mmap_arg_struct { ...@@ -155,9 +155,6 @@ struct mmap_arg_struct {
asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg) asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg)
{ {
struct mmap_arg_struct a; struct mmap_arg_struct a;
struct file *file = NULL;
unsigned long retval;
struct mm_struct *mm ;
if (copy_from_user(&a, arg, sizeof(a))) if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT; return -EFAULT;
...@@ -165,22 +162,8 @@ asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg) ...@@ -165,22 +162,8 @@ asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg)
if (a.offset & ~PAGE_MASK) if (a.offset & ~PAGE_MASK)
return -EINVAL; return -EINVAL;
if (!(a.flags & MAP_ANONYMOUS)) { return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
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,
a.offset>>PAGE_SHIFT); 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, asmlinkage long sys32_mprotect(unsigned long start, size_t len,
...@@ -483,30 +466,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, ...@@ -483,30 +466,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd,
return ret; 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) asmlinkage long sys32_olduname(struct oldold_utsname __user *name)
{ {
char *arch = "x86_64"; char *arch = "x86_64";
......
...@@ -57,9 +57,6 @@ asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32); ...@@ -57,9 +57,6 @@ asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32);
asmlinkage long sys32_personality(unsigned long); asmlinkage long sys32_personality(unsigned long);
asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
asmlinkage long sys32_mmap2(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long);
struct oldold_utsname; struct oldold_utsname;
struct old_utsname; struct old_utsname;
asmlinkage long sys32_olduname(struct oldold_utsname __user *); asmlinkage long sys32_olduname(struct oldold_utsname __user *);
......
...@@ -55,8 +55,6 @@ struct sel_arg_struct; ...@@ -55,8 +55,6 @@ struct sel_arg_struct;
struct oldold_utsname; struct oldold_utsname;
struct old_utsname; struct old_utsname;
asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long);
asmlinkage int old_mmap(struct mmap_arg_struct __user *); asmlinkage int old_mmap(struct mmap_arg_struct __user *);
asmlinkage int old_select(struct sel_arg_struct __user *); asmlinkage int old_select(struct sel_arg_struct __user *);
asmlinkage int sys_ipc(uint, int, int, int, void __user *, long); asmlinkage int sys_ipc(uint, int, int, int, void __user *, long);
......
...@@ -24,31 +24,6 @@ ...@@ -24,31 +24,6 @@
#include <asm/syscalls.h> #include <asm/syscalls.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 * Perform the select(nd, in, out, ex, tv) and mmap() system
* calls. Linux/i386 didn't use to be able to handle more than * calls. Linux/i386 didn't use to be able to handle more than
...@@ -77,7 +52,7 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) ...@@ -77,7 +52,7 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
if (a.offset & ~PAGE_MASK) if (a.offset & ~PAGE_MASK)
goto out; 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); a.fd, a.offset >> PAGE_SHIFT);
out: out:
return err; return err;
......
...@@ -23,26 +23,11 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, ...@@ -23,26 +23,11 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
unsigned long, fd, unsigned long, off) unsigned long, fd, unsigned long, off)
{ {
long error; long error;
struct file *file;
error = -EINVAL; error = -EINVAL;
if (off & ~PAGE_MASK) if (off & ~PAGE_MASK)
goto out; goto out;
error = -EBADF; error = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
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);
out: out:
return error; return error;
} }
......
...@@ -191,7 +191,7 @@ ENTRY(sys_call_table) ...@@ -191,7 +191,7 @@ ENTRY(sys_call_table)
.long sys_ni_syscall /* reserved for streams2 */ .long sys_ni_syscall /* reserved for streams2 */
.long ptregs_vfork /* 190 */ .long ptregs_vfork /* 190 */
.long sys_getrlimit .long sys_getrlimit
.long sys_mmap2 .long sys_mmap_pgoff
.long sys_truncate64 .long sys_truncate64
.long sys_ftruncate64 .long sys_ftruncate64
.long sys_stat64 /* 195 */ .long sys_stat64 /* 195 */
......
...@@ -13,8 +13,6 @@ struct sigaction; ...@@ -13,8 +13,6 @@ struct sigaction;
asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*); asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
asmlinkage long xtensa_pipe(int __user *); 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_ptrace(long, long, long, long);
asmlinkage long xtensa_sigreturn(struct pt_regs*); asmlinkage long xtensa_sigreturn(struct pt_regs*);
asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
......
...@@ -189,7 +189,7 @@ __SYSCALL( 79, sys_fremovexattr, 2) ...@@ -189,7 +189,7 @@ __SYSCALL( 79, sys_fremovexattr, 2)
/* File Map / Shared Memory Operations */ /* File Map / Shared Memory Operations */
#define __NR_mmap2 80 #define __NR_mmap2 80
__SYSCALL( 80, xtensa_mmap2, 6) __SYSCALL( 80, sys_mmap_pgoff, 6)
#define __NR_munmap 81 #define __NR_munmap 81
__SYSCALL( 81, sys_munmap, 2) __SYSCALL( 81, sys_munmap, 2)
#define __NR_mprotect 82 #define __NR_mprotect 82
......
...@@ -57,31 +57,6 @@ asmlinkage long xtensa_pipe(int __user *userfds) ...@@ -57,31 +57,6 @@ asmlinkage long xtensa_pipe(int __user *userfds)
return error; 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) asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
{ {
unsigned long ret; unsigned long ret;
......
...@@ -834,4 +834,8 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[]); ...@@ -834,4 +834,8 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
asmlinkage long sys_perf_event_open( asmlinkage long sys_perf_event_open(
struct perf_event_attr __user *attr_uptr, struct perf_event_attr __user *attr_uptr,
pid_t pid, int cpu, int group_fd, unsigned long flags); pid_t pid, int cpu, int group_fd, unsigned long flags);
asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
#endif #endif
...@@ -290,28 +290,28 @@ static unsigned long shm_get_unmapped_area(struct file *file, ...@@ -290,28 +290,28 @@ static unsigned long shm_get_unmapped_area(struct file *file,
unsigned long flags) unsigned long flags)
{ {
struct shm_file_data *sfd = shm_file_data(file); struct shm_file_data *sfd = shm_file_data(file);
return get_unmapped_area(sfd->file, addr, len, pgoff, flags); return sfd->file->f_op->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;
} }
static const struct file_operations shm_file_operations = { static const struct file_operations shm_file_operations = {
.mmap = shm_mmap, .mmap = shm_mmap,
.fsync = shm_fsync, .fsync = shm_fsync,
.release = shm_release, .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, .get_unmapped_area = shm_get_unmapped_area,
}; };
int is_file_shm_hugepages(struct file *file)
{
return file->f_op == &shm_file_operations_huge;
}
static const struct vm_operations_struct shm_vm_ops = { static const struct vm_operations_struct shm_vm_ops = {
.open = shm_open, /* callback for a new vm-area open */ .open = shm_open, /* callback for a new vm-area open */
.close = shm_close, /* callback for when the vm-area is released */ .close = shm_close, /* callback for when the vm-area is released */
...@@ -889,7 +889,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) ...@@ -889,7 +889,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
if (!sfd) if (!sfd)
goto out_put_dentry; 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) if (!file)
goto out_free; goto out_free;
ima_counts_get(file); ima_counts_get(file);
......
...@@ -931,13 +931,9 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, ...@@ -931,13 +931,9 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
if (!(flags & MAP_FIXED)) if (!(flags & MAP_FIXED))
addr = round_hint_to_min(addr); addr = round_hint_to_min(addr);
error = arch_mmap_check(addr, len, flags);
if (error)
return error;
/* Careful about overflows.. */ /* Careful about overflows.. */
len = PAGE_ALIGN(len); len = PAGE_ALIGN(len);
if (!len || len > TASK_SIZE) if (!len)
return -ENOMEM; return -ENOMEM;
/* offset overflow? */ /* offset overflow? */
...@@ -948,24 +944,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, ...@@ -948,24 +944,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
if (mm->map_count > sysctl_max_map_count) if (mm->map_count > sysctl_max_map_count)
return -ENOMEM; return -ENOMEM;
if (flags & MAP_HUGETLB) {
struct user_struct *user = NULL;
if (file)
return -EINVAL;
/*
* VM_NORESERVE is used because the reservations will be
* taken when vm_ops->mmap() is called
* A dummy user value is used because we are not locking
* memory so no accounting is necessary
*/
len = ALIGN(len, huge_page_size(&default_hstate));
file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,
&user, HUGETLB_ANONHUGE_INODE);
if (IS_ERR(file))
return PTR_ERR(file);
}
/* Obtain the address to map to. we verify (or select) it and ensure /* Obtain the address to map to. we verify (or select) it and ensure
* that it represents a valid section of the address space. * that it represents a valid section of the address space.
*/ */
...@@ -1455,6 +1433,14 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, ...@@ -1455,6 +1433,14 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
unsigned long (*get_area)(struct file *, unsigned long, unsigned long (*get_area)(struct file *, unsigned long,
unsigned long, unsigned long, 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; get_area = current->mm->get_unmapped_area;
if (file && file->f_op && file->f_op->get_unmapped_area) if (file && file->f_op && file->f_op->get_unmapped_area)
get_area = file->f_op->get_unmapped_area; get_area = file->f_op->get_unmapped_area;
...@@ -1999,20 +1985,14 @@ unsigned long do_brk(unsigned long addr, unsigned long len) ...@@ -1999,20 +1985,14 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
if (!len) if (!len)
return addr; 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); error = security_file_mmap(NULL, 0, 0, 0, addr, 1);
if (error) if (error)
return error; return error;
flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
error = arch_mmap_check(addr, len, flags); error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED);
if (error) if (error & ~PAGE_MASK)
return error; return error;
/* /*
......
...@@ -261,6 +261,137 @@ static unsigned long move_vma(struct vm_area_struct *vma, ...@@ -261,6 +261,137 @@ static unsigned long move_vma(struct vm_area_struct *vma,
return new_addr; 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 * Expand (or shrink) an existing mapping, potentially moving it at the
* same time (controlled by the MREMAP_MAYMOVE flag and available VM space) * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
...@@ -294,31 +425,9 @@ unsigned long do_mremap(unsigned long addr, ...@@ -294,31 +425,9 @@ unsigned long do_mremap(unsigned long addr,
if (!new_len) if (!new_len)
goto out; goto out;
/* new_addr is only valid if MREMAP_FIXED is specified */
if (flags & MREMAP_FIXED) { if (flags & MREMAP_FIXED) {
if (new_addr & ~PAGE_MASK) if (flags & MREMAP_MAYMOVE)
goto out; ret = mremap_to(addr, old_len, new_addr, new_len);
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; goto out;
} }
...@@ -332,60 +441,23 @@ unsigned long do_mremap(unsigned long addr, ...@@ -332,60 +441,23 @@ unsigned long do_mremap(unsigned long addr,
if (ret && old_len != new_len) if (ret && old_len != new_len)
goto out; goto out;
ret = addr; ret = addr;
if (!(flags & MREMAP_FIXED) || (new_addr == addr))
goto out; goto out;
old_len = new_len;
} }
/* /*
* Ok, we need to grow.. or relocate. * Ok, we need to grow..
*/ */
ret = -EFAULT; vma = vma_to_resize(addr, old_len, new_len, &charged);
vma = find_vma(mm, addr); if (IS_ERR(vma)) {
if (!vma || vma->vm_start > addr) 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; 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.. /* old_len exactly to the end of the area..
* And we're not relocating the area.
*/ */
if (old_len == vma->vm_end - addr && 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;
/* can we just expand the current mapping? */ /* 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; int pages = (new_len - old_len) >> PAGE_SHIFT;
vma_adjust(vma, vma->vm_start, vma_adjust(vma, vma->vm_start,
...@@ -409,13 +481,14 @@ unsigned long do_mremap(unsigned long addr, ...@@ -409,13 +481,14 @@ unsigned long do_mremap(unsigned long addr,
*/ */
ret = -ENOMEM; ret = -ENOMEM;
if (flags & MREMAP_MAYMOVE) { if (flags & MREMAP_MAYMOVE) {
if (!(flags & MREMAP_FIXED)) {
unsigned long map_flags = 0; unsigned long map_flags = 0;
if (vma->vm_flags & VM_MAYSHARE) if (vma->vm_flags & VM_MAYSHARE)
map_flags |= MAP_SHARED; map_flags |= MAP_SHARED;
new_addr = get_unmapped_area(vma->vm_file, 0, new_len, new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
vma->vm_pgoff, map_flags); vma->vm_pgoff +
((addr - vma->vm_start) >> PAGE_SHIFT),
map_flags);
if (new_addr & ~PAGE_MASK) { if (new_addr & ~PAGE_MASK) {
ret = new_addr; ret = new_addr;
goto out; goto out;
...@@ -424,13 +497,11 @@ unsigned long do_mremap(unsigned long addr, ...@@ -424,13 +497,11 @@ unsigned long do_mremap(unsigned long addr,
ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
if (ret) if (ret)
goto out; goto out;
}
ret = move_vma(vma, addr, old_len, new_len, new_addr); ret = move_vma(vma, addr, old_len, new_len, new_addr);
} }
out: out:
if (ret & ~PAGE_MASK) if (ret & ~PAGE_MASK)
vm_unacct_memory(charged); vm_unacct_memory(charged);
out_nc:
return ret; return ret;
} }
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/hugetlb.h>
#include <linux/syscalls.h>
#include <linux/mman.h>
#include <linux/file.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
...@@ -268,6 +272,46 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start, ...@@ -268,6 +272,46 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start,
} }
EXPORT_SYMBOL_GPL(get_user_pages_fast); EXPORT_SYMBOL_GPL(get_user_pages_fast);
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;
} else if (flags & MAP_HUGETLB) {
struct user_struct *user = NULL;
/*
* VM_NORESERVE is used because the reservations will be
* taken when vm_ops->mmap() is called
* A dummy user value is used because we are not locking
* memory so no accounting is necessary
*/
len = ALIGN(len, huge_page_size(&default_hstate));
file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,
&user, HUGETLB_ANONHUGE_INODE);
if (IS_ERR(file))
return PTR_ERR(file);
}
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;
}
/* Tracepoints definitions. */ /* Tracepoints definitions. */
EXPORT_TRACEPOINT_SYMBOL(kmalloc); EXPORT_TRACEPOINT_SYMBOL(kmalloc);
EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc); EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment