diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-04-20 20:13:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-04-20 20:29:13 -0400 |
commit | 6be5ceb02e98eaf6cfc4f8b12a896d04023f340d (patch) | |
tree | f34de1392300bbf63549f4eeb20f7606d6f7b1f9 | |
parent | a46ef99d80817a167477ed1c8b4d90ee0c2e726f (diff) |
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>
-rw-r--r-- | arch/tile/kernel/single_step.c | 4 | ||||
-rw-r--r-- | arch/x86/ia32/ia32_aout.c | 12 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_bufs.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i810/i810_dma.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 4 | ||||
-rw-r--r-- | fs/binfmt_aout.c | 12 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 8 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 18 | ||||
-rw-r--r-- | fs/binfmt_flat.c | 12 | ||||
-rw-r--r-- | fs/binfmt_som.c | 12 | ||||
-rw-r--r-- | include/linux/mm.h | 23 | ||||
-rw-r--r-- | mm/mmap.c | 29 | ||||
-rw-r--r-- | mm/nommu.c | 29 |
15 files changed, 87 insertions, 97 deletions
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c index 9efbc1391b3c..89529c9f0605 100644 --- a/arch/tile/kernel/single_step.c +++ b/arch/tile/kernel/single_step.c | |||
@@ -346,12 +346,10 @@ void single_step_once(struct pt_regs *regs) | |||
346 | } | 346 | } |
347 | 347 | ||
348 | /* allocate a cache line of writable, executable memory */ | 348 | /* allocate a cache line of writable, executable memory */ |
349 | down_write(¤t->mm->mmap_sem); | 349 | buffer = (void __user *) vm_mmap(NULL, 0, 64, |
350 | buffer = (void __user *) do_mmap(NULL, 0, 64, | ||
351 | PROT_EXEC | PROT_READ | PROT_WRITE, | 350 | PROT_EXEC | PROT_READ | PROT_WRITE, |
352 | MAP_PRIVATE | MAP_ANONYMOUS, | 351 | MAP_PRIVATE | MAP_ANONYMOUS, |
353 | 0); | 352 | 0); |
354 | up_write(¤t->mm->mmap_sem); | ||
355 | 353 | ||
356 | if (IS_ERR((void __force *)buffer)) { | 354 | if (IS_ERR((void __force *)buffer)) { |
357 | kfree(state); | 355 | kfree(state); |
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index b6817ee9033f..4824fb45560f 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c | |||
@@ -379,26 +379,22 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
379 | goto beyond_if; | 379 | goto beyond_if; |
380 | } | 380 | } |
381 | 381 | ||
382 | down_write(¤t->mm->mmap_sem); | 382 | error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, |
383 | error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, | ||
384 | PROT_READ | PROT_EXEC, | 383 | PROT_READ | PROT_EXEC, |
385 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | | 384 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | |
386 | MAP_EXECUTABLE | MAP_32BIT, | 385 | MAP_EXECUTABLE | MAP_32BIT, |
387 | fd_offset); | 386 | fd_offset); |
388 | up_write(¤t->mm->mmap_sem); | ||
389 | 387 | ||
390 | if (error != N_TXTADDR(ex)) { | 388 | if (error != N_TXTADDR(ex)) { |
391 | send_sig(SIGKILL, current, 0); | 389 | send_sig(SIGKILL, current, 0); |
392 | return error; | 390 | return error; |
393 | } | 391 | } |
394 | 392 | ||
395 | down_write(¤t->mm->mmap_sem); | 393 | error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data, |
396 | error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, | ||
397 | PROT_READ | PROT_WRITE | PROT_EXEC, | 394 | PROT_READ | PROT_WRITE | PROT_EXEC, |
398 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | | 395 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | |
399 | MAP_EXECUTABLE | MAP_32BIT, | 396 | MAP_EXECUTABLE | MAP_32BIT, |
400 | fd_offset + ex.a_text); | 397 | fd_offset + ex.a_text); |
401 | up_write(¤t->mm->mmap_sem); | ||
402 | if (error != N_DATADDR(ex)) { | 398 | if (error != N_DATADDR(ex)) { |
403 | send_sig(SIGKILL, current, 0); | 399 | send_sig(SIGKILL, current, 0); |
404 | return error; | 400 | return error; |
@@ -482,12 +478,10 @@ static int load_aout_library(struct file *file) | |||
482 | goto out; | 478 | goto out; |
483 | } | 479 | } |
484 | /* Now use mmap to map the library into memory. */ | 480 | /* Now use mmap to map the library into memory. */ |
485 | down_write(¤t->mm->mmap_sem); | 481 | error = vm_mmap(file, start_addr, ex.a_text + ex.a_data, |
486 | error = do_mmap(file, start_addr, ex.a_text + ex.a_data, | ||
487 | PROT_READ | PROT_WRITE | PROT_EXEC, | 482 | PROT_READ | PROT_WRITE | PROT_EXEC, |
488 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT, | 483 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT, |
489 | N_TXTOFF(ex)); | 484 | N_TXTOFF(ex)); |
490 | up_write(¤t->mm->mmap_sem); | ||
491 | retval = error; | 485 | retval = error; |
492 | if (error != start_addr) | 486 | if (error != start_addr) |
493 | goto out; | 487 | goto out; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8beb9ce79364..1457be305fb1 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -6336,13 +6336,11 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, | |||
6336 | if (npages && !old.rmap) { | 6336 | if (npages && !old.rmap) { |
6337 | unsigned long userspace_addr; | 6337 | unsigned long userspace_addr; |
6338 | 6338 | ||
6339 | down_write(¤t->mm->mmap_sem); | 6339 | userspace_addr = vm_mmap(NULL, 0, |
6340 | userspace_addr = do_mmap(NULL, 0, | ||
6341 | npages * PAGE_SIZE, | 6340 | npages * PAGE_SIZE, |
6342 | PROT_READ | PROT_WRITE, | 6341 | PROT_READ | PROT_WRITE, |
6343 | map_flags, | 6342 | map_flags, |
6344 | 0); | 6343 | 0); |
6345 | up_write(¤t->mm->mmap_sem); | ||
6346 | 6344 | ||
6347 | if (IS_ERR((void *)userspace_addr)) | 6345 | if (IS_ERR((void *)userspace_addr)) |
6348 | return PTR_ERR((void *)userspace_addr); | 6346 | return PTR_ERR((void *)userspace_addr); |
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 30372f7b2d45..348b367debeb 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c | |||
@@ -1510,8 +1510,8 @@ int drm_freebufs(struct drm_device *dev, void *data, | |||
1510 | * \param arg pointer to a drm_buf_map structure. | 1510 | * \param arg pointer to a drm_buf_map structure. |
1511 | * \return zero on success or a negative number on failure. | 1511 | * \return zero on success or a negative number on failure. |
1512 | * | 1512 | * |
1513 | * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information | 1513 | * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information |
1514 | * about each buffer into user space. For PCI buffers, it calls do_mmap() with | 1514 | * about each buffer into user space. For PCI buffers, it calls vm_mmap() with |
1515 | * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls | 1515 | * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls |
1516 | * drm_mmap_dma(). | 1516 | * drm_mmap_dma(). |
1517 | */ | 1517 | */ |
@@ -1553,18 +1553,14 @@ int drm_mapbufs(struct drm_device *dev, void *data, | |||
1553 | retcode = -EINVAL; | 1553 | retcode = -EINVAL; |
1554 | goto done; | 1554 | goto done; |
1555 | } | 1555 | } |
1556 | down_write(¤t->mm->mmap_sem); | 1556 | virtual = vm_mmap(file_priv->filp, 0, map->size, |
1557 | virtual = do_mmap(file_priv->filp, 0, map->size, | ||
1558 | PROT_READ | PROT_WRITE, | 1557 | PROT_READ | PROT_WRITE, |
1559 | MAP_SHARED, | 1558 | MAP_SHARED, |
1560 | token); | 1559 | token); |
1561 | up_write(¤t->mm->mmap_sem); | ||
1562 | } else { | 1560 | } else { |
1563 | down_write(¤t->mm->mmap_sem); | 1561 | virtual = vm_mmap(file_priv->filp, 0, dma->byte_count, |
1564 | virtual = do_mmap(file_priv->filp, 0, dma->byte_count, | ||
1565 | PROT_READ | PROT_WRITE, | 1562 | PROT_READ | PROT_WRITE, |
1566 | MAP_SHARED, 0); | 1563 | MAP_SHARED, 0); |
1567 | up_write(¤t->mm->mmap_sem); | ||
1568 | } | 1564 | } |
1569 | if (virtual > -1024UL) { | 1565 | if (virtual > -1024UL) { |
1570 | /* Real error */ | 1566 | /* Real error */ |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 26d51979116b..392ce71ed6a1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c | |||
@@ -581,10 +581,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, | |||
581 | obj->filp->f_op = &exynos_drm_gem_fops; | 581 | obj->filp->f_op = &exynos_drm_gem_fops; |
582 | obj->filp->private_data = obj; | 582 | obj->filp->private_data = obj; |
583 | 583 | ||
584 | down_write(¤t->mm->mmap_sem); | 584 | addr = vm_mmap(obj->filp, 0, args->size, |
585 | addr = do_mmap(obj->filp, 0, args->size, | ||
586 | PROT_READ | PROT_WRITE, MAP_SHARED, 0); | 585 | PROT_READ | PROT_WRITE, MAP_SHARED, 0); |
587 | up_write(¤t->mm->mmap_sem); | ||
588 | 586 | ||
589 | drm_gem_object_unreference_unlocked(obj); | 587 | drm_gem_object_unreference_unlocked(obj); |
590 | 588 | ||
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index b85337f06fbf..a4ba453b3d27 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c | |||
@@ -129,6 +129,7 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv) | |||
129 | if (buf_priv->currently_mapped == I810_BUF_MAPPED) | 129 | if (buf_priv->currently_mapped == I810_BUF_MAPPED) |
130 | return -EINVAL; | 130 | return -EINVAL; |
131 | 131 | ||
132 | /* This is all entirely broken */ | ||
132 | down_write(¤t->mm->mmap_sem); | 133 | down_write(¤t->mm->mmap_sem); |
133 | old_fops = file_priv->filp->f_op; | 134 | old_fops = file_priv->filp->f_op; |
134 | file_priv->filp->f_op = &i810_buffer_fops; | 135 | file_priv->filp->f_op = &i810_buffer_fops; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0e3c6acde955..0d1e4b7b4b99 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1087,11 +1087,9 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, | |||
1087 | if (obj == NULL) | 1087 | if (obj == NULL) |
1088 | return -ENOENT; | 1088 | return -ENOENT; |
1089 | 1089 | ||
1090 | down_write(¤t->mm->mmap_sem); | 1090 | addr = vm_mmap(obj->filp, 0, args->size, |
1091 | addr = do_mmap(obj->filp, 0, args->size, | ||
1092 | PROT_READ | PROT_WRITE, MAP_SHARED, | 1091 | PROT_READ | PROT_WRITE, MAP_SHARED, |
1093 | args->offset); | 1092 | args->offset); |
1094 | up_write(¤t->mm->mmap_sem); | ||
1095 | drm_gem_object_unreference_unlocked(obj); | 1093 | drm_gem_object_unreference_unlocked(obj); |
1096 | if (IS_ERR((void *)addr)) | 1094 | if (IS_ERR((void *)addr)) |
1097 | return addr; | 1095 | return addr; |
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index 88527492b917..d146e181d10d 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c | |||
@@ -319,24 +319,20 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
319 | goto beyond_if; | 319 | goto beyond_if; |
320 | } | 320 | } |
321 | 321 | ||
322 | down_write(¤t->mm->mmap_sem); | 322 | error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, |
323 | error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, | ||
324 | PROT_READ | PROT_EXEC, | 323 | PROT_READ | PROT_EXEC, |
325 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, | 324 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, |
326 | fd_offset); | 325 | fd_offset); |
327 | up_write(¤t->mm->mmap_sem); | ||
328 | 326 | ||
329 | if (error != N_TXTADDR(ex)) { | 327 | if (error != N_TXTADDR(ex)) { |
330 | send_sig(SIGKILL, current, 0); | 328 | send_sig(SIGKILL, current, 0); |
331 | return error; | 329 | return error; |
332 | } | 330 | } |
333 | 331 | ||
334 | down_write(¤t->mm->mmap_sem); | 332 | error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data, |
335 | error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, | ||
336 | PROT_READ | PROT_WRITE | PROT_EXEC, | 333 | PROT_READ | PROT_WRITE | PROT_EXEC, |
337 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, | 334 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, |
338 | fd_offset + ex.a_text); | 335 | fd_offset + ex.a_text); |
339 | up_write(¤t->mm->mmap_sem); | ||
340 | if (error != N_DATADDR(ex)) { | 336 | if (error != N_DATADDR(ex)) { |
341 | send_sig(SIGKILL, current, 0); | 337 | send_sig(SIGKILL, current, 0); |
342 | return error; | 338 | return error; |
@@ -417,12 +413,10 @@ static int load_aout_library(struct file *file) | |||
417 | goto out; | 413 | goto out; |
418 | } | 414 | } |
419 | /* Now use mmap to map the library into memory. */ | 415 | /* Now use mmap to map the library into memory. */ |
420 | down_write(¤t->mm->mmap_sem); | 416 | error = vm_mmap(file, start_addr, ex.a_text + ex.a_data, |
421 | error = do_mmap(file, start_addr, ex.a_text + ex.a_data, | ||
422 | PROT_READ | PROT_WRITE | PROT_EXEC, | 417 | PROT_READ | PROT_WRITE | PROT_EXEC, |
423 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, | 418 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, |
424 | N_TXTOFF(ex)); | 419 | N_TXTOFF(ex)); |
425 | up_write(¤t->mm->mmap_sem); | ||
426 | retval = error; | 420 | retval = error; |
427 | if (error != start_addr) | 421 | if (error != start_addr) |
428 | goto out; | 422 | goto out; |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 0708a0bf0ba9..16f735417072 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -958,10 +958,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
958 | and some applications "depend" upon this behavior. | 958 | and some applications "depend" upon this behavior. |
959 | Since we do not have the power to recompile these, we | 959 | Since we do not have the power to recompile these, we |
960 | emulate the SVr4 behavior. Sigh. */ | 960 | emulate the SVr4 behavior. Sigh. */ |
961 | down_write(¤t->mm->mmap_sem); | 961 | error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, |
962 | error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, | ||
963 | MAP_FIXED | MAP_PRIVATE, 0); | 962 | MAP_FIXED | MAP_PRIVATE, 0); |
964 | up_write(¤t->mm->mmap_sem); | ||
965 | } | 963 | } |
966 | 964 | ||
967 | #ifdef ELF_PLAT_INIT | 965 | #ifdef ELF_PLAT_INIT |
@@ -1046,8 +1044,7 @@ static int load_elf_library(struct file *file) | |||
1046 | eppnt++; | 1044 | eppnt++; |
1047 | 1045 | ||
1048 | /* Now use mmap to map the library into memory. */ | 1046 | /* Now use mmap to map the library into memory. */ |
1049 | down_write(¤t->mm->mmap_sem); | 1047 | error = vm_mmap(file, |
1050 | error = do_mmap(file, | ||
1051 | ELF_PAGESTART(eppnt->p_vaddr), | 1048 | ELF_PAGESTART(eppnt->p_vaddr), |
1052 | (eppnt->p_filesz + | 1049 | (eppnt->p_filesz + |
1053 | ELF_PAGEOFFSET(eppnt->p_vaddr)), | 1050 | ELF_PAGEOFFSET(eppnt->p_vaddr)), |
@@ -1055,7 +1052,6 @@ static int load_elf_library(struct file *file) | |||
1055 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, | 1052 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, |
1056 | (eppnt->p_offset - | 1053 | (eppnt->p_offset - |
1057 | ELF_PAGEOFFSET(eppnt->p_vaddr))); | 1054 | ELF_PAGEOFFSET(eppnt->p_vaddr))); |
1058 | up_write(¤t->mm->mmap_sem); | ||
1059 | if (error != ELF_PAGESTART(eppnt->p_vaddr)) | 1055 | if (error != ELF_PAGESTART(eppnt->p_vaddr)) |
1060 | goto out_free_ph; | 1056 | goto out_free_ph; |
1061 | 1057 | ||
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 9bd5612a8224..d390a0fffc65 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -390,21 +390,17 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
390 | (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC)) | 390 | (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC)) |
391 | stack_prot |= PROT_EXEC; | 391 | stack_prot |= PROT_EXEC; |
392 | 392 | ||
393 | down_write(¤t->mm->mmap_sem); | 393 | current->mm->start_brk = vm_mmap(NULL, 0, stack_size, stack_prot, |
394 | current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot, | ||
395 | MAP_PRIVATE | MAP_ANONYMOUS | | 394 | MAP_PRIVATE | MAP_ANONYMOUS | |
396 | MAP_UNINITIALIZED | MAP_GROWSDOWN, | 395 | MAP_UNINITIALIZED | MAP_GROWSDOWN, |
397 | 0); | 396 | 0); |
398 | 397 | ||
399 | if (IS_ERR_VALUE(current->mm->start_brk)) { | 398 | if (IS_ERR_VALUE(current->mm->start_brk)) { |
400 | up_write(¤t->mm->mmap_sem); | ||
401 | retval = current->mm->start_brk; | 399 | retval = current->mm->start_brk; |
402 | current->mm->start_brk = 0; | 400 | current->mm->start_brk = 0; |
403 | goto error_kill; | 401 | goto error_kill; |
404 | } | 402 | } |
405 | 403 | ||
406 | up_write(¤t->mm->mmap_sem); | ||
407 | |||
408 | current->mm->brk = current->mm->start_brk; | 404 | current->mm->brk = current->mm->start_brk; |
409 | current->mm->context.end_brk = current->mm->start_brk; | 405 | current->mm->context.end_brk = current->mm->start_brk; |
410 | current->mm->context.end_brk += | 406 | current->mm->context.end_brk += |
@@ -955,10 +951,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux( | |||
955 | if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE) | 951 | if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE) |
956 | mflags |= MAP_EXECUTABLE; | 952 | mflags |= MAP_EXECUTABLE; |
957 | 953 | ||
958 | down_write(&mm->mmap_sem); | 954 | maddr = vm_mmap(NULL, load_addr, top - base, |
959 | maddr = do_mmap(NULL, load_addr, top - base, | ||
960 | PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0); | 955 | PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0); |
961 | up_write(&mm->mmap_sem); | ||
962 | if (IS_ERR_VALUE(maddr)) | 956 | if (IS_ERR_VALUE(maddr)) |
963 | return (int) maddr; | 957 | return (int) maddr; |
964 | 958 | ||
@@ -1096,10 +1090,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, | |||
1096 | 1090 | ||
1097 | /* create the mapping */ | 1091 | /* create the mapping */ |
1098 | disp = phdr->p_vaddr & ~PAGE_MASK; | 1092 | disp = phdr->p_vaddr & ~PAGE_MASK; |
1099 | down_write(&mm->mmap_sem); | 1093 | maddr = vm_mmap(file, maddr, phdr->p_memsz + disp, prot, flags, |
1100 | maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags, | ||
1101 | phdr->p_offset - disp); | 1094 | phdr->p_offset - disp); |
1102 | up_write(&mm->mmap_sem); | ||
1103 | 1095 | ||
1104 | kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx", | 1096 | kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx", |
1105 | loop, phdr->p_memsz + disp, prot, flags, | 1097 | 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, | |||
1143 | unsigned long xmaddr; | 1135 | unsigned long xmaddr; |
1144 | 1136 | ||
1145 | flags |= MAP_FIXED | MAP_ANONYMOUS; | 1137 | flags |= MAP_FIXED | MAP_ANONYMOUS; |
1146 | down_write(&mm->mmap_sem); | 1138 | xmaddr = vm_mmap(NULL, xaddr, excess - excess1, |
1147 | xmaddr = do_mmap(NULL, xaddr, excess - excess1, | ||
1148 | prot, flags, 0); | 1139 | prot, flags, 0); |
1149 | up_write(&mm->mmap_sem); | ||
1150 | 1140 | ||
1151 | kdebug("mmap[%d] <anon>" | 1141 | kdebug("mmap[%d] <anon>" |
1152 | " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx", | 1142 | " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx", |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 024d20ee3ca3..6b2daf99fab8 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -542,10 +542,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
542 | */ | 542 | */ |
543 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); | 543 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); |
544 | 544 | ||
545 | down_write(¤t->mm->mmap_sem); | 545 | textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, |
546 | textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, | ||
547 | MAP_PRIVATE|MAP_EXECUTABLE, 0); | 546 | MAP_PRIVATE|MAP_EXECUTABLE, 0); |
548 | up_write(¤t->mm->mmap_sem); | ||
549 | if (!textpos || IS_ERR_VALUE(textpos)) { | 547 | if (!textpos || IS_ERR_VALUE(textpos)) { |
550 | if (!textpos) | 548 | if (!textpos) |
551 | textpos = (unsigned long) -ENOMEM; | 549 | textpos = (unsigned long) -ENOMEM; |
@@ -556,10 +554,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
556 | 554 | ||
557 | len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | 555 | len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); |
558 | len = PAGE_ALIGN(len); | 556 | len = PAGE_ALIGN(len); |
559 | down_write(¤t->mm->mmap_sem); | 557 | realdatastart = vm_mmap(0, 0, len, |
560 | realdatastart = do_mmap(0, 0, len, | ||
561 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); | 558 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); |
562 | up_write(¤t->mm->mmap_sem); | ||
563 | 559 | ||
564 | if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) { | 560 | if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) { |
565 | if (!realdatastart) | 561 | if (!realdatastart) |
@@ -603,10 +599,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
603 | 599 | ||
604 | len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | 600 | len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); |
605 | len = PAGE_ALIGN(len); | 601 | len = PAGE_ALIGN(len); |
606 | down_write(¤t->mm->mmap_sem); | 602 | textpos = vm_mmap(0, 0, len, |
607 | textpos = do_mmap(0, 0, len, | ||
608 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); | 603 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); |
609 | up_write(¤t->mm->mmap_sem); | ||
610 | 604 | ||
611 | if (!textpos || IS_ERR_VALUE(textpos)) { | 605 | if (!textpos || IS_ERR_VALUE(textpos)) { |
612 | if (!textpos) | 606 | if (!textpos) |
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c index e4fc746629a7..4517aaff61b4 100644 --- a/fs/binfmt_som.c +++ b/fs/binfmt_som.c | |||
@@ -147,10 +147,8 @@ static int map_som_binary(struct file *file, | |||
147 | code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize); | 147 | code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize); |
148 | current->mm->start_code = code_start; | 148 | current->mm->start_code = code_start; |
149 | current->mm->end_code = code_start + code_size; | 149 | current->mm->end_code = code_start + code_size; |
150 | down_write(¤t->mm->mmap_sem); | 150 | retval = vm_mmap(file, code_start, code_size, prot, |
151 | retval = do_mmap(file, code_start, code_size, prot, | ||
152 | flags, SOM_PAGESTART(hpuxhdr->exec_tfile)); | 151 | flags, SOM_PAGESTART(hpuxhdr->exec_tfile)); |
153 | up_write(¤t->mm->mmap_sem); | ||
154 | if (retval < 0 && retval > -1024) | 152 | if (retval < 0 && retval > -1024) |
155 | goto out; | 153 | goto out; |
156 | 154 | ||
@@ -158,20 +156,16 @@ static int map_som_binary(struct file *file, | |||
158 | data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize); | 156 | data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize); |
159 | current->mm->start_data = data_start; | 157 | current->mm->start_data = data_start; |
160 | current->mm->end_data = bss_start = data_start + data_size; | 158 | current->mm->end_data = bss_start = data_start + data_size; |
161 | down_write(¤t->mm->mmap_sem); | 159 | retval = vm_mmap(file, data_start, data_size, |
162 | retval = do_mmap(file, data_start, data_size, | ||
163 | prot | PROT_WRITE, flags, | 160 | prot | PROT_WRITE, flags, |
164 | SOM_PAGESTART(hpuxhdr->exec_dfile)); | 161 | SOM_PAGESTART(hpuxhdr->exec_dfile)); |
165 | up_write(¤t->mm->mmap_sem); | ||
166 | if (retval < 0 && retval > -1024) | 162 | if (retval < 0 && retval > -1024) |
167 | goto out; | 163 | goto out; |
168 | 164 | ||
169 | som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize); | 165 | som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize); |
170 | current->mm->start_brk = current->mm->brk = som_brk; | 166 | current->mm->start_brk = current->mm->brk = som_brk; |
171 | down_write(¤t->mm->mmap_sem); | 167 | retval = vm_mmap(NULL, bss_start, som_brk - bss_start, |
172 | retval = do_mmap(NULL, bss_start, som_brk - bss_start, | ||
173 | prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0); | 168 | prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0); |
174 | up_write(¤t->mm->mmap_sem); | ||
175 | if (retval > 0 || retval < -1024) | 169 | if (retval > 0 || retval < -1024) |
176 | retval = 0; | 170 | retval = 0; |
177 | out: | 171 | out: |
diff --git a/include/linux/mm.h b/include/linux/mm.h index cb61950a3aa1..86a692c3b238 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1393,31 +1393,20 @@ extern int install_special_mapping(struct mm_struct *mm, | |||
1393 | 1393 | ||
1394 | extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); | 1394 | extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); |
1395 | 1395 | ||
1396 | extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | ||
1397 | unsigned long len, unsigned long prot, | ||
1398 | unsigned long flag, unsigned long pgoff); | ||
1399 | extern unsigned long mmap_region(struct file *file, unsigned long addr, | 1396 | extern unsigned long mmap_region(struct file *file, unsigned long addr, |
1400 | unsigned long len, unsigned long flags, | 1397 | unsigned long len, unsigned long flags, |
1401 | vm_flags_t vm_flags, unsigned long pgoff); | 1398 | vm_flags_t vm_flags, unsigned long pgoff); |
1402 | 1399 | extern unsigned long do_mmap(struct file *, unsigned long, | |
1403 | static inline unsigned long do_mmap(struct file *file, unsigned long addr, | 1400 | unsigned long, unsigned long, |
1404 | unsigned long len, unsigned long prot, | 1401 | unsigned long, unsigned long); |
1405 | unsigned long flag, unsigned long offset) | ||
1406 | { | ||
1407 | unsigned long ret = -EINVAL; | ||
1408 | if ((offset + PAGE_ALIGN(len)) < offset) | ||
1409 | goto out; | ||
1410 | if (!(offset & ~PAGE_MASK)) | ||
1411 | ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); | ||
1412 | out: | ||
1413 | return ret; | ||
1414 | } | ||
1415 | |||
1416 | extern int do_munmap(struct mm_struct *, unsigned long, size_t); | 1402 | extern int do_munmap(struct mm_struct *, unsigned long, size_t); |
1417 | 1403 | ||
1418 | /* These take the mm semaphore themselves */ | 1404 | /* These take the mm semaphore themselves */ |
1419 | extern unsigned long vm_brk(unsigned long, unsigned long); | 1405 | extern unsigned long vm_brk(unsigned long, unsigned long); |
1420 | extern int vm_munmap(struct mm_struct *, unsigned long, size_t); | 1406 | extern int vm_munmap(struct mm_struct *, unsigned long, size_t); |
1407 | extern unsigned long vm_mmap(struct file *, unsigned long, | ||
1408 | unsigned long, unsigned long, | ||
1409 | unsigned long, unsigned long); | ||
1421 | 1410 | ||
1422 | /* truncate.c */ | 1411 | /* truncate.c */ |
1423 | extern void truncate_inode_pages(struct address_space *, loff_t); | 1412 | extern void truncate_inode_pages(struct address_space *, loff_t); |
@@ -953,7 +953,7 @@ static inline unsigned long round_hint_to_min(unsigned long hint) | |||
953 | * The caller must hold down_write(¤t->mm->mmap_sem). | 953 | * The caller must hold down_write(¤t->mm->mmap_sem). |
954 | */ | 954 | */ |
955 | 955 | ||
956 | unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | 956 | static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, |
957 | unsigned long len, unsigned long prot, | 957 | unsigned long len, unsigned long prot, |
958 | unsigned long flags, unsigned long pgoff) | 958 | unsigned long flags, unsigned long pgoff) |
959 | { | 959 | { |
@@ -1089,7 +1089,32 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
1089 | 1089 | ||
1090 | return mmap_region(file, addr, len, flags, vm_flags, pgoff); | 1090 | return mmap_region(file, addr, len, flags, vm_flags, pgoff); |
1091 | } | 1091 | } |
1092 | EXPORT_SYMBOL(do_mmap_pgoff); | 1092 | |
1093 | unsigned long do_mmap(struct file *file, unsigned long addr, | ||
1094 | unsigned long len, unsigned long prot, | ||
1095 | unsigned long flag, unsigned long offset) | ||
1096 | { | ||
1097 | if (unlikely(offset + PAGE_ALIGN(len) < offset)) | ||
1098 | return -EINVAL; | ||
1099 | if (unlikely(offset & ~PAGE_MASK)) | ||
1100 | return -EINVAL; | ||
1101 | return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); | ||
1102 | } | ||
1103 | EXPORT_SYMBOL(do_mmap); | ||
1104 | |||
1105 | unsigned long vm_mmap(struct file *file, unsigned long addr, | ||
1106 | unsigned long len, unsigned long prot, | ||
1107 | unsigned long flag, unsigned long offset) | ||
1108 | { | ||
1109 | unsigned long ret; | ||
1110 | struct mm_struct *mm = current->mm; | ||
1111 | |||
1112 | down_write(&mm->mmap_sem); | ||
1113 | ret = do_mmap(file, addr, len, prot, flag, offset); | ||
1114 | up_write(&mm->mmap_sem); | ||
1115 | return ret; | ||
1116 | } | ||
1117 | EXPORT_SYMBOL(vm_mmap); | ||
1093 | 1118 | ||
1094 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | 1119 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, |
1095 | unsigned long, prot, unsigned long, flags, | 1120 | unsigned long, prot, unsigned long, flags, |
diff --git a/mm/nommu.c b/mm/nommu.c index 11a69b22bd4b..dd00383be2d9 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -1233,7 +1233,7 @@ enomem: | |||
1233 | /* | 1233 | /* |
1234 | * handle mapping creation for uClinux | 1234 | * handle mapping creation for uClinux |
1235 | */ | 1235 | */ |
1236 | unsigned long do_mmap_pgoff(struct file *file, | 1236 | static unsigned long do_mmap_pgoff(struct file *file, |
1237 | unsigned long addr, | 1237 | unsigned long addr, |
1238 | unsigned long len, | 1238 | unsigned long len, |
1239 | unsigned long prot, | 1239 | unsigned long prot, |
@@ -1470,7 +1470,32 @@ error_getting_region: | |||
1470 | show_free_areas(0); | 1470 | show_free_areas(0); |
1471 | return -ENOMEM; | 1471 | return -ENOMEM; |
1472 | } | 1472 | } |
1473 | EXPORT_SYMBOL(do_mmap_pgoff); | 1473 | |
1474 | unsigned long do_mmap(struct file *file, unsigned long addr, | ||
1475 | unsigned long len, unsigned long prot, | ||
1476 | unsigned long flag, unsigned long offset) | ||
1477 | { | ||
1478 | if (unlikely(offset + PAGE_ALIGN(len) < offset)) | ||
1479 | return -EINVAL; | ||
1480 | if (unlikely(offset & ~PAGE_MASK)) | ||
1481 | return -EINVAL; | ||
1482 | return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); | ||
1483 | } | ||
1484 | EXPORT_SYMBOL(do_mmap); | ||
1485 | |||
1486 | unsigned long vm_mmap(struct file *file, unsigned long addr, | ||
1487 | unsigned long len, unsigned long prot, | ||
1488 | unsigned long flag, unsigned long offset) | ||
1489 | { | ||
1490 | unsigned long ret; | ||
1491 | struct mm_struct *mm = current->mm; | ||
1492 | |||
1493 | down_write(&mm->mmap_sem); | ||
1494 | ret = do_mmap(file, addr, len, prot, flag, offset); | ||
1495 | up_write(&mm->mmap_sem); | ||
1496 | return ret; | ||
1497 | } | ||
1498 | EXPORT_SYMBOL(vm_mmap); | ||
1474 | 1499 | ||
1475 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | 1500 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, |
1476 | unsigned long, prot, unsigned long, flags, | 1501 | unsigned long, prot, unsigned long, flags, |