summaryrefslogtreecommitdiffstats
path: root/include/linux/pagemap.h
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2016-05-20 19:57:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-20 20:58:30 -0400
commitb8ca9e3a612eaf3e54c6fa136c62246a1a9aece7 (patch)
tree4738aff27fdf4f88f77deaebd30454f94ea63a44 /include/linux/pagemap.h
parent297880f4af4e492ed5084be9397d65a18ade56ee (diff)
mm: tighten fault_in_pages_writeable()
copy_page_to_iter_iovec() is currently the only user of fault_in_pages_writeable(), and it definitely can use fragments from high order pages. Make sure fault_in_pages_writeable() is only touching two adjacent pages at most, as claimed. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/pagemap.h')
-rw-r--r--include/linux/pagemap.h24
1 files changed, 9 insertions, 15 deletions
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index fe1513ffb7bf..97354102794d 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -518,33 +518,27 @@ void page_endio(struct page *page, int rw, int err);
518extern void add_page_wait_queue(struct page *page, wait_queue_t *waiter); 518extern void add_page_wait_queue(struct page *page, wait_queue_t *waiter);
519 519
520/* 520/*
521 * Fault a userspace page into pagetables. Return non-zero on a fault. 521 * Fault one or two userspace pages into pagetables.
522 * 522 * Return -EINVAL if more than two pages would be needed.
523 * This assumes that two userspace pages are always sufficient. 523 * Return non-zero on a fault.
524 */ 524 */
525static inline int fault_in_pages_writeable(char __user *uaddr, int size) 525static inline int fault_in_pages_writeable(char __user *uaddr, int size)
526{ 526{
527 int ret; 527 int span, ret;
528 528
529 if (unlikely(size == 0)) 529 if (unlikely(size == 0))
530 return 0; 530 return 0;
531 531
532 span = offset_in_page(uaddr) + size;
533 if (span > 2 * PAGE_SIZE)
534 return -EINVAL;
532 /* 535 /*
533 * Writing zeroes into userspace here is OK, because we know that if 536 * Writing zeroes into userspace here is OK, because we know that if
534 * the zero gets there, we'll be overwriting it. 537 * the zero gets there, we'll be overwriting it.
535 */ 538 */
536 ret = __put_user(0, uaddr); 539 ret = __put_user(0, uaddr);
537 if (ret == 0) { 540 if (ret == 0 && span > PAGE_SIZE)
538 char __user *end = uaddr + size - 1; 541 ret = __put_user(0, uaddr + size - 1);
539
540 /*
541 * If the page was already mapped, this will get a cache miss
542 * for sure, so try to avoid doing it.
543 */
544 if (((unsigned long)uaddr & PAGE_MASK) !=
545 ((unsigned long)end & PAGE_MASK))
546 ret = __put_user(0, end);
547 }
548 return ret; 542 return ret;
549} 543}
550 544