diff options
Diffstat (limited to 'mm/nommu.c')
-rw-r--r-- | mm/nommu.c | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/mm/nommu.c b/mm/nommu.c index 5189b5aed8c0..6f9248f89bde 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -1143,9 +1143,6 @@ static int do_mmap_private(struct vm_area_struct *vma, | |||
1143 | if (ret < rlen) | 1143 | if (ret < rlen) |
1144 | memset(base + ret, 0, rlen - ret); | 1144 | memset(base + ret, 0, rlen - ret); |
1145 | 1145 | ||
1146 | } else { | ||
1147 | /* if it's an anonymous mapping, then just clear it */ | ||
1148 | memset(base, 0, rlen); | ||
1149 | } | 1146 | } |
1150 | 1147 | ||
1151 | return 0; | 1148 | return 0; |
@@ -1343,6 +1340,11 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
1343 | goto error_just_free; | 1340 | goto error_just_free; |
1344 | add_nommu_region(region); | 1341 | add_nommu_region(region); |
1345 | 1342 | ||
1343 | /* clear anonymous mappings that don't ask for uninitialized data */ | ||
1344 | if (!vma->vm_file && !(flags & MAP_UNINITIALIZED)) | ||
1345 | memset((void *)region->vm_start, 0, | ||
1346 | region->vm_end - region->vm_start); | ||
1347 | |||
1346 | /* okay... we have a mapping; now we have to register it */ | 1348 | /* okay... we have a mapping; now we have to register it */ |
1347 | result = vma->vm_start; | 1349 | result = vma->vm_start; |
1348 | 1350 | ||
@@ -1362,9 +1364,11 @@ share: | |||
1362 | error_just_free: | 1364 | error_just_free: |
1363 | up_write(&nommu_region_sem); | 1365 | up_write(&nommu_region_sem); |
1364 | error: | 1366 | error: |
1365 | fput(region->vm_file); | 1367 | if (region->vm_file) |
1368 | fput(region->vm_file); | ||
1366 | kmem_cache_free(vm_region_jar, region); | 1369 | kmem_cache_free(vm_region_jar, region); |
1367 | fput(vma->vm_file); | 1370 | if (vma->vm_file) |
1371 | fput(vma->vm_file); | ||
1368 | if (vma->vm_flags & VM_EXECUTABLE) | 1372 | if (vma->vm_flags & VM_EXECUTABLE) |
1369 | removed_exe_file_vma(vma->vm_mm); | 1373 | removed_exe_file_vma(vma->vm_mm); |
1370 | kmem_cache_free(vm_area_cachep, vma); | 1374 | kmem_cache_free(vm_area_cachep, vma); |
@@ -1394,6 +1398,31 @@ error_getting_region: | |||
1394 | } | 1398 | } |
1395 | EXPORT_SYMBOL(do_mmap_pgoff); | 1399 | EXPORT_SYMBOL(do_mmap_pgoff); |
1396 | 1400 | ||
1401 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | ||
1402 | unsigned long, prot, unsigned long, flags, | ||
1403 | unsigned long, fd, unsigned long, pgoff) | ||
1404 | { | ||
1405 | struct file *file = NULL; | ||
1406 | unsigned long retval = -EBADF; | ||
1407 | |||
1408 | if (!(flags & MAP_ANONYMOUS)) { | ||
1409 | file = fget(fd); | ||
1410 | if (!file) | ||
1411 | goto out; | ||
1412 | } | ||
1413 | |||
1414 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
1415 | |||
1416 | down_write(¤t->mm->mmap_sem); | ||
1417 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
1418 | up_write(¤t->mm->mmap_sem); | ||
1419 | |||
1420 | if (file) | ||
1421 | fput(file); | ||
1422 | out: | ||
1423 | return retval; | ||
1424 | } | ||
1425 | |||
1397 | /* | 1426 | /* |
1398 | * split a vma into two pieces at address 'addr', a new vma is allocated either | 1427 | * split a vma into two pieces at address 'addr', a new vma is allocated either |
1399 | * for the first part or the tail. | 1428 | * for the first part or the tail. |