diff options
-rw-r--r-- | mm/internal.h | 5 | ||||
-rw-r--r-- | mm/madvise.c | 8 | ||||
-rw-r--r-- | mm/mlock.c | 16 | ||||
-rw-r--r-- | mm/mmap.c | 27 | ||||
-rw-r--r-- | mm/mprotect.c | 3 | ||||
-rw-r--r-- | mm/mremap.c | 3 | ||||
-rw-r--r-- | mm/nommu.c | 2 | ||||
-rw-r--r-- | mm/util.c | 12 |
8 files changed, 55 insertions, 21 deletions
diff --git a/mm/internal.h b/mm/internal.h index f6f3353b0868..bff7fd702331 100644 --- a/mm/internal.h +++ b/mm/internal.h | |||
@@ -442,9 +442,10 @@ extern u64 hwpoison_filter_flags_value; | |||
442 | extern u64 hwpoison_filter_memcg; | 442 | extern u64 hwpoison_filter_memcg; |
443 | extern u32 hwpoison_filter_enable; | 443 | extern u32 hwpoison_filter_enable; |
444 | 444 | ||
445 | extern unsigned long vm_mmap_pgoff(struct file *, unsigned long, | 445 | extern unsigned long __must_check vm_mmap_pgoff(struct file *, unsigned long, |
446 | unsigned long, unsigned long, | 446 | unsigned long, unsigned long, |
447 | unsigned long, unsigned long); | 447 | unsigned long, unsigned long, |
448 | bool); | ||
448 | 449 | ||
449 | extern void set_pageblock_order(void); | 450 | extern void set_pageblock_order(void); |
450 | unsigned long reclaim_clean_pages_from_list(struct zone *zone, | 451 | unsigned long reclaim_clean_pages_from_list(struct zone *zone, |
diff --git a/mm/madvise.c b/mm/madvise.c index 07427d3fcead..93fb63e88b5e 100644 --- a/mm/madvise.c +++ b/mm/madvise.c | |||
@@ -707,10 +707,12 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) | |||
707 | return error; | 707 | return error; |
708 | 708 | ||
709 | write = madvise_need_mmap_write(behavior); | 709 | write = madvise_need_mmap_write(behavior); |
710 | if (write) | 710 | if (write) { |
711 | down_write(¤t->mm->mmap_sem); | 711 | if (down_write_killable(¤t->mm->mmap_sem)) |
712 | else | 712 | return -EINTR; |
713 | } else { | ||
713 | down_read(¤t->mm->mmap_sem); | 714 | down_read(¤t->mm->mmap_sem); |
715 | } | ||
714 | 716 | ||
715 | /* | 717 | /* |
716 | * If the interval [start,end) covers some unmapped address | 718 | * If the interval [start,end) covers some unmapped address |
diff --git a/mm/mlock.c b/mm/mlock.c index 96f001041928..ef8dc9f395c4 100644 --- a/mm/mlock.c +++ b/mm/mlock.c | |||
@@ -617,7 +617,7 @@ static int apply_vma_lock_flags(unsigned long start, size_t len, | |||
617 | return error; | 617 | return error; |
618 | } | 618 | } |
619 | 619 | ||
620 | static int do_mlock(unsigned long start, size_t len, vm_flags_t flags) | 620 | static __must_check int do_mlock(unsigned long start, size_t len, vm_flags_t flags) |
621 | { | 621 | { |
622 | unsigned long locked; | 622 | unsigned long locked; |
623 | unsigned long lock_limit; | 623 | unsigned long lock_limit; |
@@ -635,7 +635,8 @@ static int do_mlock(unsigned long start, size_t len, vm_flags_t flags) | |||
635 | lock_limit >>= PAGE_SHIFT; | 635 | lock_limit >>= PAGE_SHIFT; |
636 | locked = len >> PAGE_SHIFT; | 636 | locked = len >> PAGE_SHIFT; |
637 | 637 | ||
638 | down_write(¤t->mm->mmap_sem); | 638 | if (down_write_killable(¤t->mm->mmap_sem)) |
639 | return -EINTR; | ||
639 | 640 | ||
640 | locked += current->mm->locked_vm; | 641 | locked += current->mm->locked_vm; |
641 | 642 | ||
@@ -678,7 +679,8 @@ SYSCALL_DEFINE2(munlock, unsigned long, start, size_t, len) | |||
678 | len = PAGE_ALIGN(len + (offset_in_page(start))); | 679 | len = PAGE_ALIGN(len + (offset_in_page(start))); |
679 | start &= PAGE_MASK; | 680 | start &= PAGE_MASK; |
680 | 681 | ||
681 | down_write(¤t->mm->mmap_sem); | 682 | if (down_write_killable(¤t->mm->mmap_sem)) |
683 | return -EINTR; | ||
682 | ret = apply_vma_lock_flags(start, len, 0); | 684 | ret = apply_vma_lock_flags(start, len, 0); |
683 | up_write(¤t->mm->mmap_sem); | 685 | up_write(¤t->mm->mmap_sem); |
684 | 686 | ||
@@ -748,9 +750,10 @@ SYSCALL_DEFINE1(mlockall, int, flags) | |||
748 | lock_limit = rlimit(RLIMIT_MEMLOCK); | 750 | lock_limit = rlimit(RLIMIT_MEMLOCK); |
749 | lock_limit >>= PAGE_SHIFT; | 751 | lock_limit >>= PAGE_SHIFT; |
750 | 752 | ||
751 | ret = -ENOMEM; | 753 | if (down_write_killable(¤t->mm->mmap_sem)) |
752 | down_write(¤t->mm->mmap_sem); | 754 | return -EINTR; |
753 | 755 | ||
756 | ret = -ENOMEM; | ||
754 | if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) || | 757 | if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) || |
755 | capable(CAP_IPC_LOCK)) | 758 | capable(CAP_IPC_LOCK)) |
756 | ret = apply_mlockall_flags(flags); | 759 | ret = apply_mlockall_flags(flags); |
@@ -765,7 +768,8 @@ SYSCALL_DEFINE0(munlockall) | |||
765 | { | 768 | { |
766 | int ret; | 769 | int ret; |
767 | 770 | ||
768 | down_write(¤t->mm->mmap_sem); | 771 | if (down_write_killable(¤t->mm->mmap_sem)) |
772 | return -EINTR; | ||
769 | ret = apply_mlockall_flags(0); | 773 | ret = apply_mlockall_flags(0); |
770 | up_write(¤t->mm->mmap_sem); | 774 | up_write(¤t->mm->mmap_sem); |
771 | return ret; | 775 | return ret; |
@@ -178,7 +178,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) | |||
178 | unsigned long min_brk; | 178 | unsigned long min_brk; |
179 | bool populate; | 179 | bool populate; |
180 | 180 | ||
181 | down_write(&mm->mmap_sem); | 181 | if (down_write_killable(&mm->mmap_sem)) |
182 | return -EINTR; | ||
182 | 183 | ||
183 | #ifdef CONFIG_COMPAT_BRK | 184 | #ifdef CONFIG_COMPAT_BRK |
184 | /* | 185 | /* |
@@ -1332,7 +1333,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | |||
1332 | 1333 | ||
1333 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | 1334 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); |
1334 | 1335 | ||
1335 | retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff); | 1336 | retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff, true); |
1336 | out_fput: | 1337 | out_fput: |
1337 | if (file) | 1338 | if (file) |
1338 | fput(file); | 1339 | fput(file); |
@@ -2493,6 +2494,10 @@ int vm_munmap(unsigned long start, size_t len) | |||
2493 | int ret; | 2494 | int ret; |
2494 | struct mm_struct *mm = current->mm; | 2495 | struct mm_struct *mm = current->mm; |
2495 | 2496 | ||
2497 | /* | ||
2498 | * XXX convert to down_write_killable as soon as all users are able | ||
2499 | * to handle the error. | ||
2500 | */ | ||
2496 | down_write(&mm->mmap_sem); | 2501 | down_write(&mm->mmap_sem); |
2497 | ret = do_munmap(mm, start, len); | 2502 | ret = do_munmap(mm, start, len); |
2498 | up_write(&mm->mmap_sem); | 2503 | up_write(&mm->mmap_sem); |
@@ -2502,8 +2507,15 @@ EXPORT_SYMBOL(vm_munmap); | |||
2502 | 2507 | ||
2503 | SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) | 2508 | SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) |
2504 | { | 2509 | { |
2510 | int ret; | ||
2511 | struct mm_struct *mm = current->mm; | ||
2512 | |||
2505 | profile_munmap(addr); | 2513 | profile_munmap(addr); |
2506 | return vm_munmap(addr, len); | 2514 | if (down_write_killable(&mm->mmap_sem)) |
2515 | return -EINTR; | ||
2516 | ret = do_munmap(mm, addr, len); | ||
2517 | up_write(&mm->mmap_sem); | ||
2518 | return ret; | ||
2507 | } | 2519 | } |
2508 | 2520 | ||
2509 | 2521 | ||
@@ -2535,7 +2547,9 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, | |||
2535 | if (pgoff + (size >> PAGE_SHIFT) < pgoff) | 2547 | if (pgoff + (size >> PAGE_SHIFT) < pgoff) |
2536 | return ret; | 2548 | return ret; |
2537 | 2549 | ||
2538 | down_write(&mm->mmap_sem); | 2550 | if (down_write_killable(&mm->mmap_sem)) |
2551 | return -EINTR; | ||
2552 | |||
2539 | vma = find_vma(mm, start); | 2553 | vma = find_vma(mm, start); |
2540 | 2554 | ||
2541 | if (!vma || !(vma->vm_flags & VM_SHARED)) | 2555 | if (!vma || !(vma->vm_flags & VM_SHARED)) |
@@ -2700,6 +2714,11 @@ unsigned long vm_brk(unsigned long addr, unsigned long len) | |||
2700 | unsigned long ret; | 2714 | unsigned long ret; |
2701 | bool populate; | 2715 | bool populate; |
2702 | 2716 | ||
2717 | /* | ||
2718 | * XXX not all users are chcecking the return value, convert | ||
2719 | * to down_write_killable after they are able to cope with | ||
2720 | * error | ||
2721 | */ | ||
2703 | down_write(&mm->mmap_sem); | 2722 | down_write(&mm->mmap_sem); |
2704 | ret = do_brk(addr, len); | 2723 | ret = do_brk(addr, len); |
2705 | populate = ((mm->def_flags & VM_LOCKED) != 0); | 2724 | populate = ((mm->def_flags & VM_LOCKED) != 0); |
diff --git a/mm/mprotect.c b/mm/mprotect.c index b650c5412f58..5019a1ef2848 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c | |||
@@ -379,7 +379,8 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len, | |||
379 | 379 | ||
380 | reqprot = prot; | 380 | reqprot = prot; |
381 | 381 | ||
382 | down_write(¤t->mm->mmap_sem); | 382 | if (down_write_killable(¤t->mm->mmap_sem)) |
383 | return -EINTR; | ||
383 | 384 | ||
384 | vma = find_vma(current->mm, start); | 385 | vma = find_vma(current->mm, start); |
385 | error = -ENOMEM; | 386 | error = -ENOMEM; |
diff --git a/mm/mremap.c b/mm/mremap.c index 9dc499977924..1f157adfdaf9 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
@@ -503,7 +503,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, | |||
503 | if (!new_len) | 503 | if (!new_len) |
504 | return ret; | 504 | return ret; |
505 | 505 | ||
506 | down_write(¤t->mm->mmap_sem); | 506 | if (down_write_killable(¤t->mm->mmap_sem)) |
507 | return -EINTR; | ||
507 | 508 | ||
508 | if (flags & MREMAP_FIXED) { | 509 | if (flags & MREMAP_FIXED) { |
509 | ret = mremap_to(addr, old_len, new_addr, new_len, | 510 | ret = mremap_to(addr, old_len, new_addr, new_len, |
diff --git a/mm/nommu.c b/mm/nommu.c index c8bd59a03c71..b74512746aae 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -1446,7 +1446,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | |||
1446 | 1446 | ||
1447 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | 1447 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); |
1448 | 1448 | ||
1449 | retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff); | 1449 | retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff, true); |
1450 | 1450 | ||
1451 | if (file) | 1451 | if (file) |
1452 | fput(file); | 1452 | fput(file); |
@@ -289,7 +289,7 @@ EXPORT_SYMBOL_GPL(get_user_pages_fast); | |||
289 | 289 | ||
290 | unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, | 290 | unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, |
291 | unsigned long len, unsigned long prot, | 291 | unsigned long len, unsigned long prot, |
292 | unsigned long flag, unsigned long pgoff) | 292 | unsigned long flag, unsigned long pgoff, bool killable) |
293 | { | 293 | { |
294 | unsigned long ret; | 294 | unsigned long ret; |
295 | struct mm_struct *mm = current->mm; | 295 | struct mm_struct *mm = current->mm; |
@@ -297,7 +297,12 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, | |||
297 | 297 | ||
298 | ret = security_mmap_file(file, prot, flag); | 298 | ret = security_mmap_file(file, prot, flag); |
299 | if (!ret) { | 299 | if (!ret) { |
300 | down_write(&mm->mmap_sem); | 300 | if (killable) { |
301 | if (down_write_killable(&mm->mmap_sem)) | ||
302 | return -EINTR; | ||
303 | } else { | ||
304 | down_write(&mm->mmap_sem); | ||
305 | } | ||
301 | ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff, | 306 | ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff, |
302 | &populate); | 307 | &populate); |
303 | up_write(&mm->mmap_sem); | 308 | up_write(&mm->mmap_sem); |
@@ -307,6 +312,7 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, | |||
307 | return ret; | 312 | return ret; |
308 | } | 313 | } |
309 | 314 | ||
315 | /* XXX are all callers checking an error */ | ||
310 | unsigned long vm_mmap(struct file *file, unsigned long addr, | 316 | unsigned long vm_mmap(struct file *file, unsigned long addr, |
311 | unsigned long len, unsigned long prot, | 317 | unsigned long len, unsigned long prot, |
312 | unsigned long flag, unsigned long offset) | 318 | unsigned long flag, unsigned long offset) |
@@ -316,7 +322,7 @@ unsigned long vm_mmap(struct file *file, unsigned long addr, | |||
316 | if (unlikely(offset_in_page(offset))) | 322 | if (unlikely(offset_in_page(offset))) |
317 | return -EINVAL; | 323 | return -EINVAL; |
318 | 324 | ||
319 | return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); | 325 | return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT, false); |
320 | } | 326 | } |
321 | EXPORT_SYMBOL(vm_mmap); | 327 | EXPORT_SYMBOL(vm_mmap); |
322 | 328 | ||