diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/mmap.c | 40 | ||||
| -rw-r--r-- | mm/nommu.c | 42 | ||||
| -rw-r--r-- | mm/slab.c | 4 | ||||
| -rw-r--r-- | mm/util.c | 44 |
4 files changed, 79 insertions, 51 deletions
| @@ -1043,6 +1043,46 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
| 1043 | } | 1043 | } |
| 1044 | EXPORT_SYMBOL(do_mmap_pgoff); | 1044 | EXPORT_SYMBOL(do_mmap_pgoff); |
| 1045 | 1045 | ||
| 1046 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | ||
| 1047 | unsigned long, prot, unsigned long, flags, | ||
| 1048 | unsigned long, fd, unsigned long, pgoff) | ||
| 1049 | { | ||
| 1050 | struct file *file = NULL; | ||
| 1051 | unsigned long retval = -EBADF; | ||
| 1052 | |||
| 1053 | if (!(flags & MAP_ANONYMOUS)) { | ||
| 1054 | if (unlikely(flags & MAP_HUGETLB)) | ||
| 1055 | return -EINVAL; | ||
| 1056 | file = fget(fd); | ||
| 1057 | if (!file) | ||
| 1058 | goto out; | ||
| 1059 | } else if (flags & MAP_HUGETLB) { | ||
| 1060 | struct user_struct *user = NULL; | ||
| 1061 | /* | ||
| 1062 | * VM_NORESERVE is used because the reservations will be | ||
| 1063 | * taken when vm_ops->mmap() is called | ||
| 1064 | * A dummy user value is used because we are not locking | ||
| 1065 | * memory so no accounting is necessary | ||
| 1066 | */ | ||
| 1067 | len = ALIGN(len, huge_page_size(&default_hstate)); | ||
| 1068 | file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, | ||
| 1069 | &user, HUGETLB_ANONHUGE_INODE); | ||
| 1070 | if (IS_ERR(file)) | ||
| 1071 | return PTR_ERR(file); | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
| 1075 | |||
| 1076 | down_write(¤t->mm->mmap_sem); | ||
| 1077 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
| 1078 | up_write(¤t->mm->mmap_sem); | ||
| 1079 | |||
| 1080 | if (file) | ||
| 1081 | fput(file); | ||
| 1082 | out: | ||
| 1083 | return retval; | ||
| 1084 | } | ||
| 1085 | |||
| 1046 | /* | 1086 | /* |
| 1047 | * Some shared mappigns will want the pages marked read-only | 1087 | * Some shared mappigns will want the pages marked read-only |
| 1048 | * to track write events. If so, we'll downgrade vm_page_prot | 1088 | * to track write events. If so, we'll downgrade vm_page_prot |
diff --git a/mm/nommu.c b/mm/nommu.c index 8687973462bb..17773862619b 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
| @@ -432,6 +432,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) | |||
| 432 | /* | 432 | /* |
| 433 | * Ok, looks good - let it rip. | 433 | * Ok, looks good - let it rip. |
| 434 | */ | 434 | */ |
| 435 | flush_icache_range(mm->brk, brk); | ||
| 435 | return mm->brk = brk; | 436 | return mm->brk = brk; |
| 436 | } | 437 | } |
| 437 | 438 | ||
| @@ -1353,10 +1354,14 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
| 1353 | share: | 1354 | share: |
| 1354 | add_vma_to_mm(current->mm, vma); | 1355 | add_vma_to_mm(current->mm, vma); |
| 1355 | 1356 | ||
| 1356 | up_write(&nommu_region_sem); | 1357 | /* we flush the region from the icache only when the first executable |
| 1358 | * mapping of it is made */ | ||
| 1359 | if (vma->vm_flags & VM_EXEC && !region->vm_icache_flushed) { | ||
| 1360 | flush_icache_range(region->vm_start, region->vm_end); | ||
| 1361 | region->vm_icache_flushed = true; | ||
| 1362 | } | ||
| 1357 | 1363 | ||
| 1358 | if (prot & PROT_EXEC) | 1364 | up_write(&nommu_region_sem); |
| 1359 | flush_icache_range(result, result + len); | ||
| 1360 | 1365 | ||
| 1361 | kleave(" = %lx", result); | 1366 | kleave(" = %lx", result); |
| 1362 | return result; | 1367 | return result; |
| @@ -1398,6 +1403,31 @@ error_getting_region: | |||
| 1398 | } | 1403 | } |
| 1399 | EXPORT_SYMBOL(do_mmap_pgoff); | 1404 | EXPORT_SYMBOL(do_mmap_pgoff); |
| 1400 | 1405 | ||
| 1406 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | ||
| 1407 | unsigned long, prot, unsigned long, flags, | ||
| 1408 | unsigned long, fd, unsigned long, pgoff) | ||
| 1409 | { | ||
| 1410 | struct file *file = NULL; | ||
| 1411 | unsigned long retval = -EBADF; | ||
| 1412 | |||
| 1413 | if (!(flags & MAP_ANONYMOUS)) { | ||
| 1414 | file = fget(fd); | ||
| 1415 | if (!file) | ||
| 1416 | goto out; | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
| 1420 | |||
| 1421 | down_write(¤t->mm->mmap_sem); | ||
| 1422 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
| 1423 | up_write(¤t->mm->mmap_sem); | ||
| 1424 | |||
| 1425 | if (file) | ||
| 1426 | fput(file); | ||
| 1427 | out: | ||
| 1428 | return retval; | ||
| 1429 | } | ||
| 1430 | |||
| 1401 | /* | 1431 | /* |
| 1402 | * split a vma into two pieces at address 'addr', a new vma is allocated either | 1432 | * split a vma into two pieces at address 'addr', a new vma is allocated either |
| 1403 | * for the first part or the tail. | 1433 | * for the first part or the tail. |
| @@ -1891,9 +1921,11 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in | |||
| 1891 | 1921 | ||
| 1892 | /* only read or write mappings where it is permitted */ | 1922 | /* only read or write mappings where it is permitted */ |
| 1893 | if (write && vma->vm_flags & VM_MAYWRITE) | 1923 | if (write && vma->vm_flags & VM_MAYWRITE) |
| 1894 | len -= copy_to_user((void *) addr, buf, len); | 1924 | copy_to_user_page(vma, NULL, addr, |
| 1925 | (void *) addr, buf, len); | ||
| 1895 | else if (!write && vma->vm_flags & VM_MAYREAD) | 1926 | else if (!write && vma->vm_flags & VM_MAYREAD) |
| 1896 | len -= copy_from_user(buf, (void *) addr, len); | 1927 | copy_from_user_page(vma, NULL, addr, |
| 1928 | buf, (void *) addr, len); | ||
| 1897 | else | 1929 | else |
| 1898 | len = 0; | 1930 | len = 0; |
| 1899 | } else { | 1931 | } else { |
| @@ -654,7 +654,7 @@ static void init_node_lock_keys(int q) | |||
| 654 | 654 | ||
| 655 | l3 = s->cs_cachep->nodelists[q]; | 655 | l3 = s->cs_cachep->nodelists[q]; |
| 656 | if (!l3 || OFF_SLAB(s->cs_cachep)) | 656 | if (!l3 || OFF_SLAB(s->cs_cachep)) |
| 657 | return; | 657 | continue; |
| 658 | lockdep_set_class(&l3->list_lock, &on_slab_l3_key); | 658 | lockdep_set_class(&l3->list_lock, &on_slab_l3_key); |
| 659 | alc = l3->alien; | 659 | alc = l3->alien; |
| 660 | /* | 660 | /* |
| @@ -665,7 +665,7 @@ static void init_node_lock_keys(int q) | |||
| 665 | * for alloc_alien_cache, | 665 | * for alloc_alien_cache, |
| 666 | */ | 666 | */ |
| 667 | if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC) | 667 | if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC) |
| 668 | return; | 668 | continue; |
| 669 | for_each_node(r) { | 669 | for_each_node(r) { |
| 670 | if (alc[r]) | 670 | if (alc[r]) |
| 671 | lockdep_set_class(&alc[r]->lock, | 671 | lockdep_set_class(&alc[r]->lock, |
| @@ -4,10 +4,6 @@ | |||
| 4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
| 5 | #include <linux/err.h> | 5 | #include <linux/err.h> |
| 6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
| 7 | #include <linux/hugetlb.h> | ||
| 8 | #include <linux/syscalls.h> | ||
| 9 | #include <linux/mman.h> | ||
| 10 | #include <linux/file.h> | ||
| 11 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
| 12 | 8 | ||
| 13 | #define CREATE_TRACE_POINTS | 9 | #define CREATE_TRACE_POINTS |
| @@ -272,46 +268,6 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start, | |||
| 272 | } | 268 | } |
| 273 | EXPORT_SYMBOL_GPL(get_user_pages_fast); | 269 | EXPORT_SYMBOL_GPL(get_user_pages_fast); |
| 274 | 270 | ||
| 275 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | ||
| 276 | unsigned long, prot, unsigned long, flags, | ||
| 277 | unsigned long, fd, unsigned long, pgoff) | ||
| 278 | { | ||
| 279 | struct file * file = NULL; | ||
| 280 | unsigned long retval = -EBADF; | ||
| 281 | |||
| 282 | if (!(flags & MAP_ANONYMOUS)) { | ||
| 283 | if (unlikely(flags & MAP_HUGETLB)) | ||
| 284 | return -EINVAL; | ||
| 285 | file = fget(fd); | ||
| 286 | if (!file) | ||
| 287 | goto out; | ||
| 288 | } else if (flags & MAP_HUGETLB) { | ||
| 289 | struct user_struct *user = NULL; | ||
| 290 | /* | ||
| 291 | * VM_NORESERVE is used because the reservations will be | ||
| 292 | * taken when vm_ops->mmap() is called | ||
| 293 | * A dummy user value is used because we are not locking | ||
| 294 | * memory so no accounting is necessary | ||
| 295 | */ | ||
| 296 | len = ALIGN(len, huge_page_size(&default_hstate)); | ||
| 297 | file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, | ||
| 298 | &user, HUGETLB_ANONHUGE_INODE); | ||
| 299 | if (IS_ERR(file)) | ||
| 300 | return PTR_ERR(file); | ||
| 301 | } | ||
| 302 | |||
| 303 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
| 304 | |||
| 305 | down_write(¤t->mm->mmap_sem); | ||
| 306 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
| 307 | up_write(¤t->mm->mmap_sem); | ||
| 308 | |||
| 309 | if (file) | ||
| 310 | fput(file); | ||
| 311 | out: | ||
| 312 | return retval; | ||
| 313 | } | ||
| 314 | |||
| 315 | /* Tracepoints definitions. */ | 271 | /* Tracepoints definitions. */ |
| 316 | EXPORT_TRACEPOINT_SYMBOL(kmalloc); | 272 | EXPORT_TRACEPOINT_SYMBOL(kmalloc); |
| 317 | EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc); | 273 | EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc); |
