VM: add "vm_mmap()" helper function
This continues the theme started with vm_brk() and vm_munmap(): vm_mmap() does the same thing as do_mmap(), but additionally does the required VM locking. This uninlines (and rewrites it to be clearer) do_mmap(), which sadly duplicates it in mm/mmap.c and mm/nommu.c. But that way we don't have to export our internal do_mmap_pgoff() function. Some day we hopefully don't have to export do_mmap() either, if all modular users can become the simpler vm_mmap() instead. We're actually very close to that already, with the notable exception of the (broken) use in i810, and a couple of stragglers in binfmt_elf. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
a46ef99d80
commit
6be5ceb02e
15 changed files with 87 additions and 97 deletions
|
@ -346,12 +346,10 @@ void single_step_once(struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a cache line of writable, executable memory */
|
/* allocate a cache line of writable, executable memory */
|
||||||
down_write(¤t->mm->mmap_sem);
|
buffer = (void __user *) vm_mmap(NULL, 0, 64,
|
||||||
buffer = (void __user *) do_mmap(NULL, 0, 64,
|
|
||||||
PROT_EXEC | PROT_READ | PROT_WRITE,
|
PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS,
|
MAP_PRIVATE | MAP_ANONYMOUS,
|
||||||
0);
|
0);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
|
|
||||||
if (IS_ERR((void __force *)buffer)) {
|
if (IS_ERR((void __force *)buffer)) {
|
||||||
kfree(state);
|
kfree(state);
|
||||||
|
|
|
@ -379,26 +379,22 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
||||||
goto beyond_if;
|
goto beyond_if;
|
||||||
}
|
}
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
|
||||||
error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
|
|
||||||
PROT_READ | PROT_EXEC,
|
PROT_READ | PROT_EXEC,
|
||||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
|
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
|
||||||
MAP_EXECUTABLE | MAP_32BIT,
|
MAP_EXECUTABLE | MAP_32BIT,
|
||||||
fd_offset);
|
fd_offset);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
|
|
||||||
if (error != N_TXTADDR(ex)) {
|
if (error != N_TXTADDR(ex)) {
|
||||||
send_sig(SIGKILL, current, 0);
|
send_sig(SIGKILL, current, 0);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
|
||||||
error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
|
|
||||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
|
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
|
||||||
MAP_EXECUTABLE | MAP_32BIT,
|
MAP_EXECUTABLE | MAP_32BIT,
|
||||||
fd_offset + ex.a_text);
|
fd_offset + ex.a_text);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
if (error != N_DATADDR(ex)) {
|
if (error != N_DATADDR(ex)) {
|
||||||
send_sig(SIGKILL, current, 0);
|
send_sig(SIGKILL, current, 0);
|
||||||
return error;
|
return error;
|
||||||
|
@ -482,12 +478,10 @@ static int load_aout_library(struct file *file)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* Now use mmap to map the library into memory. */
|
/* Now use mmap to map the library into memory. */
|
||||||
down_write(¤t->mm->mmap_sem);
|
error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
|
||||||
error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
|
|
||||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
|
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
|
||||||
N_TXTOFF(ex));
|
N_TXTOFF(ex));
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
retval = error;
|
retval = error;
|
||||||
if (error != start_addr)
|
if (error != start_addr)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -6336,13 +6336,11 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||||
if (npages && !old.rmap) {
|
if (npages && !old.rmap) {
|
||||||
unsigned long userspace_addr;
|
unsigned long userspace_addr;
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
userspace_addr = vm_mmap(NULL, 0,
|
||||||
userspace_addr = do_mmap(NULL, 0,
|
|
||||||
npages * PAGE_SIZE,
|
npages * PAGE_SIZE,
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
map_flags,
|
map_flags,
|
||||||
0);
|
0);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
|
|
||||||
if (IS_ERR((void *)userspace_addr))
|
if (IS_ERR((void *)userspace_addr))
|
||||||
return PTR_ERR((void *)userspace_addr);
|
return PTR_ERR((void *)userspace_addr);
|
||||||
|
|
|
@ -1510,8 +1510,8 @@ int drm_freebufs(struct drm_device *dev, void *data,
|
||||||
* \param arg pointer to a drm_buf_map structure.
|
* \param arg pointer to a drm_buf_map structure.
|
||||||
* \return zero on success or a negative number on failure.
|
* \return zero on success or a negative number on failure.
|
||||||
*
|
*
|
||||||
* Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information
|
* Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
|
||||||
* about each buffer into user space. For PCI buffers, it calls do_mmap() with
|
* about each buffer into user space. For PCI buffers, it calls vm_mmap() with
|
||||||
* offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
|
* offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
|
||||||
* drm_mmap_dma().
|
* drm_mmap_dma().
|
||||||
*/
|
*/
|
||||||
|
@ -1553,18 +1553,14 @@ int drm_mapbufs(struct drm_device *dev, void *data,
|
||||||
retcode = -EINVAL;
|
retcode = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
down_write(¤t->mm->mmap_sem);
|
virtual = vm_mmap(file_priv->filp, 0, map->size,
|
||||||
virtual = do_mmap(file_priv->filp, 0, map->size,
|
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED,
|
MAP_SHARED,
|
||||||
token);
|
token);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
} else {
|
} else {
|
||||||
down_write(¤t->mm->mmap_sem);
|
virtual = vm_mmap(file_priv->filp, 0, dma->byte_count,
|
||||||
virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
|
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED, 0);
|
MAP_SHARED, 0);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
}
|
}
|
||||||
if (virtual > -1024UL) {
|
if (virtual > -1024UL) {
|
||||||
/* Real error */
|
/* Real error */
|
||||||
|
|
|
@ -581,10 +581,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||||
obj->filp->f_op = &exynos_drm_gem_fops;
|
obj->filp->f_op = &exynos_drm_gem_fops;
|
||||||
obj->filp->private_data = obj;
|
obj->filp->private_data = obj;
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
addr = vm_mmap(obj->filp, 0, args->size,
|
||||||
addr = do_mmap(obj->filp, 0, args->size,
|
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED, 0);
|
PROT_READ | PROT_WRITE, MAP_SHARED, 0);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
|
|
||||||
drm_gem_object_unreference_unlocked(obj);
|
drm_gem_object_unreference_unlocked(obj);
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,7 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
|
||||||
if (buf_priv->currently_mapped == I810_BUF_MAPPED)
|
if (buf_priv->currently_mapped == I810_BUF_MAPPED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* This is all entirely broken */
|
||||||
down_write(¤t->mm->mmap_sem);
|
down_write(¤t->mm->mmap_sem);
|
||||||
old_fops = file_priv->filp->f_op;
|
old_fops = file_priv->filp->f_op;
|
||||||
file_priv->filp->f_op = &i810_buffer_fops;
|
file_priv->filp->f_op = &i810_buffer_fops;
|
||||||
|
|
|
@ -1087,11 +1087,9 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||||
if (obj == NULL)
|
if (obj == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
addr = vm_mmap(obj->filp, 0, args->size,
|
||||||
addr = do_mmap(obj->filp, 0, args->size,
|
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED,
|
PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
args->offset);
|
args->offset);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
drm_gem_object_unreference_unlocked(obj);
|
drm_gem_object_unreference_unlocked(obj);
|
||||||
if (IS_ERR((void *)addr))
|
if (IS_ERR((void *)addr))
|
||||||
return addr;
|
return addr;
|
||||||
|
|
|
@ -319,24 +319,20 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
||||||
goto beyond_if;
|
goto beyond_if;
|
||||||
}
|
}
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
|
||||||
error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
|
|
||||||
PROT_READ | PROT_EXEC,
|
PROT_READ | PROT_EXEC,
|
||||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
|
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
|
||||||
fd_offset);
|
fd_offset);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
|
|
||||||
if (error != N_TXTADDR(ex)) {
|
if (error != N_TXTADDR(ex)) {
|
||||||
send_sig(SIGKILL, current, 0);
|
send_sig(SIGKILL, current, 0);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
|
||||||
error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
|
|
||||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
|
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
|
||||||
fd_offset + ex.a_text);
|
fd_offset + ex.a_text);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
if (error != N_DATADDR(ex)) {
|
if (error != N_DATADDR(ex)) {
|
||||||
send_sig(SIGKILL, current, 0);
|
send_sig(SIGKILL, current, 0);
|
||||||
return error;
|
return error;
|
||||||
|
@ -417,12 +413,10 @@ static int load_aout_library(struct file *file)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* Now use mmap to map the library into memory. */
|
/* Now use mmap to map the library into memory. */
|
||||||
down_write(¤t->mm->mmap_sem);
|
error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
|
||||||
error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
|
|
||||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
|
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
|
||||||
N_TXTOFF(ex));
|
N_TXTOFF(ex));
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
retval = error;
|
retval = error;
|
||||||
if (error != start_addr)
|
if (error != start_addr)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -958,10 +958,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
||||||
and some applications "depend" upon this behavior.
|
and some applications "depend" upon this behavior.
|
||||||
Since we do not have the power to recompile these, we
|
Since we do not have the power to recompile these, we
|
||||||
emulate the SVr4 behavior. Sigh. */
|
emulate the SVr4 behavior. Sigh. */
|
||||||
down_write(¤t->mm->mmap_sem);
|
error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
|
||||||
error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
|
|
||||||
MAP_FIXED | MAP_PRIVATE, 0);
|
MAP_FIXED | MAP_PRIVATE, 0);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ELF_PLAT_INIT
|
#ifdef ELF_PLAT_INIT
|
||||||
|
@ -1046,8 +1044,7 @@ static int load_elf_library(struct file *file)
|
||||||
eppnt++;
|
eppnt++;
|
||||||
|
|
||||||
/* Now use mmap to map the library into memory. */
|
/* Now use mmap to map the library into memory. */
|
||||||
down_write(¤t->mm->mmap_sem);
|
error = vm_mmap(file,
|
||||||
error = do_mmap(file,
|
|
||||||
ELF_PAGESTART(eppnt->p_vaddr),
|
ELF_PAGESTART(eppnt->p_vaddr),
|
||||||
(eppnt->p_filesz +
|
(eppnt->p_filesz +
|
||||||
ELF_PAGEOFFSET(eppnt->p_vaddr)),
|
ELF_PAGEOFFSET(eppnt->p_vaddr)),
|
||||||
|
@ -1055,7 +1052,6 @@ static int load_elf_library(struct file *file)
|
||||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
|
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
|
||||||
(eppnt->p_offset -
|
(eppnt->p_offset -
|
||||||
ELF_PAGEOFFSET(eppnt->p_vaddr)));
|
ELF_PAGEOFFSET(eppnt->p_vaddr)));
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
if (error != ELF_PAGESTART(eppnt->p_vaddr))
|
if (error != ELF_PAGESTART(eppnt->p_vaddr))
|
||||||
goto out_free_ph;
|
goto out_free_ph;
|
||||||
|
|
||||||
|
|
|
@ -390,21 +390,17 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
|
||||||
(executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
|
(executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
|
||||||
stack_prot |= PROT_EXEC;
|
stack_prot |= PROT_EXEC;
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
current->mm->start_brk = vm_mmap(NULL, 0, stack_size, stack_prot,
|
||||||
current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
|
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS |
|
MAP_PRIVATE | MAP_ANONYMOUS |
|
||||||
MAP_UNINITIALIZED | MAP_GROWSDOWN,
|
MAP_UNINITIALIZED | MAP_GROWSDOWN,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (IS_ERR_VALUE(current->mm->start_brk)) {
|
if (IS_ERR_VALUE(current->mm->start_brk)) {
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
retval = current->mm->start_brk;
|
retval = current->mm->start_brk;
|
||||||
current->mm->start_brk = 0;
|
current->mm->start_brk = 0;
|
||||||
goto error_kill;
|
goto error_kill;
|
||||||
}
|
}
|
||||||
|
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
|
|
||||||
current->mm->brk = current->mm->start_brk;
|
current->mm->brk = current->mm->start_brk;
|
||||||
current->mm->context.end_brk = current->mm->start_brk;
|
current->mm->context.end_brk = current->mm->start_brk;
|
||||||
current->mm->context.end_brk +=
|
current->mm->context.end_brk +=
|
||||||
|
@ -955,10 +951,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
|
||||||
if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
|
if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
|
||||||
mflags |= MAP_EXECUTABLE;
|
mflags |= MAP_EXECUTABLE;
|
||||||
|
|
||||||
down_write(&mm->mmap_sem);
|
maddr = vm_mmap(NULL, load_addr, top - base,
|
||||||
maddr = do_mmap(NULL, load_addr, top - base,
|
|
||||||
PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
|
PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
|
||||||
up_write(&mm->mmap_sem);
|
|
||||||
if (IS_ERR_VALUE(maddr))
|
if (IS_ERR_VALUE(maddr))
|
||||||
return (int) maddr;
|
return (int) maddr;
|
||||||
|
|
||||||
|
@ -1096,10 +1090,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
|
||||||
|
|
||||||
/* create the mapping */
|
/* create the mapping */
|
||||||
disp = phdr->p_vaddr & ~PAGE_MASK;
|
disp = phdr->p_vaddr & ~PAGE_MASK;
|
||||||
down_write(&mm->mmap_sem);
|
maddr = vm_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
|
||||||
maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
|
|
||||||
phdr->p_offset - disp);
|
phdr->p_offset - disp);
|
||||||
up_write(&mm->mmap_sem);
|
|
||||||
|
|
||||||
kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
|
kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
|
||||||
loop, phdr->p_memsz + disp, prot, flags,
|
loop, phdr->p_memsz + disp, prot, flags,
|
||||||
|
@ -1143,10 +1135,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
|
||||||
unsigned long xmaddr;
|
unsigned long xmaddr;
|
||||||
|
|
||||||
flags |= MAP_FIXED | MAP_ANONYMOUS;
|
flags |= MAP_FIXED | MAP_ANONYMOUS;
|
||||||
down_write(&mm->mmap_sem);
|
xmaddr = vm_mmap(NULL, xaddr, excess - excess1,
|
||||||
xmaddr = do_mmap(NULL, xaddr, excess - excess1,
|
|
||||||
prot, flags, 0);
|
prot, flags, 0);
|
||||||
up_write(&mm->mmap_sem);
|
|
||||||
|
|
||||||
kdebug("mmap[%d] <anon>"
|
kdebug("mmap[%d] <anon>"
|
||||||
" ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
|
" ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
|
||||||
|
|
|
@ -542,10 +542,8 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||||
*/
|
*/
|
||||||
DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
|
DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
|
||||||
textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
|
|
||||||
MAP_PRIVATE|MAP_EXECUTABLE, 0);
|
MAP_PRIVATE|MAP_EXECUTABLE, 0);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
if (!textpos || IS_ERR_VALUE(textpos)) {
|
if (!textpos || IS_ERR_VALUE(textpos)) {
|
||||||
if (!textpos)
|
if (!textpos)
|
||||||
textpos = (unsigned long) -ENOMEM;
|
textpos = (unsigned long) -ENOMEM;
|
||||||
|
@ -556,10 +554,8 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||||
|
|
||||||
len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
|
len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
|
||||||
len = PAGE_ALIGN(len);
|
len = PAGE_ALIGN(len);
|
||||||
down_write(¤t->mm->mmap_sem);
|
realdatastart = vm_mmap(0, 0, len,
|
||||||
realdatastart = do_mmap(0, 0, len,
|
|
||||||
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
|
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
|
|
||||||
if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
|
if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
|
||||||
if (!realdatastart)
|
if (!realdatastart)
|
||||||
|
@ -603,10 +599,8 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||||
|
|
||||||
len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
|
len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
|
||||||
len = PAGE_ALIGN(len);
|
len = PAGE_ALIGN(len);
|
||||||
down_write(¤t->mm->mmap_sem);
|
textpos = vm_mmap(0, 0, len,
|
||||||
textpos = do_mmap(0, 0, len,
|
|
||||||
PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
|
PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
|
|
||||||
if (!textpos || IS_ERR_VALUE(textpos)) {
|
if (!textpos || IS_ERR_VALUE(textpos)) {
|
||||||
if (!textpos)
|
if (!textpos)
|
||||||
|
|
|
@ -147,10 +147,8 @@ static int map_som_binary(struct file *file,
|
||||||
code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize);
|
code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize);
|
||||||
current->mm->start_code = code_start;
|
current->mm->start_code = code_start;
|
||||||
current->mm->end_code = code_start + code_size;
|
current->mm->end_code = code_start + code_size;
|
||||||
down_write(¤t->mm->mmap_sem);
|
retval = vm_mmap(file, code_start, code_size, prot,
|
||||||
retval = do_mmap(file, code_start, code_size, prot,
|
|
||||||
flags, SOM_PAGESTART(hpuxhdr->exec_tfile));
|
flags, SOM_PAGESTART(hpuxhdr->exec_tfile));
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
if (retval < 0 && retval > -1024)
|
if (retval < 0 && retval > -1024)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -158,20 +156,16 @@ static int map_som_binary(struct file *file,
|
||||||
data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize);
|
data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize);
|
||||||
current->mm->start_data = data_start;
|
current->mm->start_data = data_start;
|
||||||
current->mm->end_data = bss_start = data_start + data_size;
|
current->mm->end_data = bss_start = data_start + data_size;
|
||||||
down_write(¤t->mm->mmap_sem);
|
retval = vm_mmap(file, data_start, data_size,
|
||||||
retval = do_mmap(file, data_start, data_size,
|
|
||||||
prot | PROT_WRITE, flags,
|
prot | PROT_WRITE, flags,
|
||||||
SOM_PAGESTART(hpuxhdr->exec_dfile));
|
SOM_PAGESTART(hpuxhdr->exec_dfile));
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
if (retval < 0 && retval > -1024)
|
if (retval < 0 && retval > -1024)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize);
|
som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize);
|
||||||
current->mm->start_brk = current->mm->brk = som_brk;
|
current->mm->start_brk = current->mm->brk = som_brk;
|
||||||
down_write(¤t->mm->mmap_sem);
|
retval = vm_mmap(NULL, bss_start, som_brk - bss_start,
|
||||||
retval = do_mmap(NULL, bss_start, som_brk - bss_start,
|
|
||||||
prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0);
|
prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0);
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
if (retval > 0 || retval < -1024)
|
if (retval > 0 || retval < -1024)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -1393,31 +1393,20 @@ extern int install_special_mapping(struct mm_struct *mm,
|
||||||
|
|
||||||
extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
|
extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
|
||||||
|
|
||||||
extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
|
|
||||||
unsigned long len, unsigned long prot,
|
|
||||||
unsigned long flag, unsigned long pgoff);
|
|
||||||
extern unsigned long mmap_region(struct file *file, unsigned long addr,
|
extern unsigned long mmap_region(struct file *file, unsigned long addr,
|
||||||
unsigned long len, unsigned long flags,
|
unsigned long len, unsigned long flags,
|
||||||
vm_flags_t vm_flags, unsigned long pgoff);
|
vm_flags_t vm_flags, unsigned long pgoff);
|
||||||
|
extern unsigned long do_mmap(struct file *, unsigned long,
|
||||||
static inline unsigned long do_mmap(struct file *file, unsigned long addr,
|
unsigned long, unsigned long,
|
||||||
unsigned long len, unsigned long prot,
|
unsigned long, unsigned long);
|
||||||
unsigned long flag, unsigned long offset)
|
|
||||||
{
|
|
||||||
unsigned long ret = -EINVAL;
|
|
||||||
if ((offset + PAGE_ALIGN(len)) < offset)
|
|
||||||
goto out;
|
|
||||||
if (!(offset & ~PAGE_MASK))
|
|
||||||
ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int do_munmap(struct mm_struct *, unsigned long, size_t);
|
extern int do_munmap(struct mm_struct *, unsigned long, size_t);
|
||||||
|
|
||||||
/* These take the mm semaphore themselves */
|
/* These take the mm semaphore themselves */
|
||||||
extern unsigned long vm_brk(unsigned long, unsigned long);
|
extern unsigned long vm_brk(unsigned long, unsigned long);
|
||||||
extern int vm_munmap(struct mm_struct *, unsigned long, size_t);
|
extern int vm_munmap(struct mm_struct *, unsigned long, size_t);
|
||||||
|
extern unsigned long vm_mmap(struct file *, unsigned long,
|
||||||
|
unsigned long, unsigned long,
|
||||||
|
unsigned long, unsigned long);
|
||||||
|
|
||||||
/* truncate.c */
|
/* truncate.c */
|
||||||
extern void truncate_inode_pages(struct address_space *, loff_t);
|
extern void truncate_inode_pages(struct address_space *, loff_t);
|
||||||
|
|
29
mm/mmap.c
29
mm/mmap.c
|
@ -953,7 +953,7 @@ static inline unsigned long round_hint_to_min(unsigned long hint)
|
||||||
* The caller must hold down_write(¤t->mm->mmap_sem).
|
* The caller must hold down_write(¤t->mm->mmap_sem).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
|
static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
|
||||||
unsigned long len, unsigned long prot,
|
unsigned long len, unsigned long prot,
|
||||||
unsigned long flags, unsigned long pgoff)
|
unsigned long flags, unsigned long pgoff)
|
||||||
{
|
{
|
||||||
|
@ -1089,7 +1089,32 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
|
||||||
|
|
||||||
return mmap_region(file, addr, len, flags, vm_flags, pgoff);
|
return mmap_region(file, addr, len, flags, vm_flags, pgoff);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(do_mmap_pgoff);
|
|
||||||
|
unsigned long do_mmap(struct file *file, unsigned long addr,
|
||||||
|
unsigned long len, unsigned long prot,
|
||||||
|
unsigned long flag, unsigned long offset)
|
||||||
|
{
|
||||||
|
if (unlikely(offset + PAGE_ALIGN(len) < offset))
|
||||||
|
return -EINVAL;
|
||||||
|
if (unlikely(offset & ~PAGE_MASK))
|
||||||
|
return -EINVAL;
|
||||||
|
return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(do_mmap);
|
||||||
|
|
||||||
|
unsigned long vm_mmap(struct file *file, unsigned long addr,
|
||||||
|
unsigned long len, unsigned long prot,
|
||||||
|
unsigned long flag, unsigned long offset)
|
||||||
|
{
|
||||||
|
unsigned long ret;
|
||||||
|
struct mm_struct *mm = current->mm;
|
||||||
|
|
||||||
|
down_write(&mm->mmap_sem);
|
||||||
|
ret = do_mmap(file, addr, len, prot, flag, offset);
|
||||||
|
up_write(&mm->mmap_sem);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(vm_mmap);
|
||||||
|
|
||||||
SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
|
SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
|
||||||
unsigned long, prot, unsigned long, flags,
|
unsigned long, prot, unsigned long, flags,
|
||||||
|
|
29
mm/nommu.c
29
mm/nommu.c
|
@ -1233,7 +1233,7 @@ static int do_mmap_private(struct vm_area_struct *vma,
|
||||||
/*
|
/*
|
||||||
* handle mapping creation for uClinux
|
* handle mapping creation for uClinux
|
||||||
*/
|
*/
|
||||||
unsigned long do_mmap_pgoff(struct file *file,
|
static unsigned long do_mmap_pgoff(struct file *file,
|
||||||
unsigned long addr,
|
unsigned long addr,
|
||||||
unsigned long len,
|
unsigned long len,
|
||||||
unsigned long prot,
|
unsigned long prot,
|
||||||
|
@ -1470,7 +1470,32 @@ unsigned long do_mmap_pgoff(struct file *file,
|
||||||
show_free_areas(0);
|
show_free_areas(0);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(do_mmap_pgoff);
|
|
||||||
|
unsigned long do_mmap(struct file *file, unsigned long addr,
|
||||||
|
unsigned long len, unsigned long prot,
|
||||||
|
unsigned long flag, unsigned long offset)
|
||||||
|
{
|
||||||
|
if (unlikely(offset + PAGE_ALIGN(len) < offset))
|
||||||
|
return -EINVAL;
|
||||||
|
if (unlikely(offset & ~PAGE_MASK))
|
||||||
|
return -EINVAL;
|
||||||
|
return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(do_mmap);
|
||||||
|
|
||||||
|
unsigned long vm_mmap(struct file *file, unsigned long addr,
|
||||||
|
unsigned long len, unsigned long prot,
|
||||||
|
unsigned long flag, unsigned long offset)
|
||||||
|
{
|
||||||
|
unsigned long ret;
|
||||||
|
struct mm_struct *mm = current->mm;
|
||||||
|
|
||||||
|
down_write(&mm->mmap_sem);
|
||||||
|
ret = do_mmap(file, addr, len, prot, flag, offset);
|
||||||
|
up_write(&mm->mmap_sem);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(vm_mmap);
|
||||||
|
|
||||||
SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
|
SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
|
||||||
unsigned long, prot, unsigned long, flags,
|
unsigned long, prot, unsigned long, flags,
|
||||||
|
|
Loading…
Reference in a new issue