Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1388089
| From | Eric Dumazet <eric.dumazet@gmail.com> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [PATCH] mm: tighten fault_in_pages_writeable() |
| Date | 2016-04-26 23:00 +0200 |
| Message-ID | <rsifn-5Sr-1@gated-at.bofh.it> (permalink) |
| Organization | linux.* mail to news gateway |
From: Eric Dumazet <edumazet@google.com>
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>
---
include/linux/pagemap.h | 24 +++++++++---------------
1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 7e1ab155c67c..83eb89e8d276 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);
extern void add_page_wait_queue(struct page *page, wait_queue_t *waiter);
/*
- * Fault a userspace page into pagetables. Return non-zero on a fault.
- *
- * This assumes that two userspace pages are always sufficient.
+ * Fault one or two userspace pages into pagetables.
+ * Return -EINVAL if more than two pages would be needed.
+ * Return non-zero on a fault.
*/
static inline int fault_in_pages_writeable(char __user *uaddr, int size)
{
- int ret;
+ int span, ret;
if (unlikely(size == 0))
return 0;
+ span = offset_in_page(uaddr) + size;
+ if (span > 2 * PAGE_SIZE)
+ return -EINVAL;
/*
* Writing zeroes into userspace here is OK, because we know that if
* the zero gets there, we'll be overwriting it.
*/
ret = __put_user(0, uaddr);
- if (ret == 0) {
- char __user *end = uaddr + size - 1;
-
- /*
- * If the page was already mapped, this will get a cache miss
- * for sure, so try to avoid doing it.
- */
- if (((unsigned long)uaddr & PAGE_MASK) !=
- ((unsigned long)end & PAGE_MASK))
- ret = __put_user(0, end);
- }
+ if (ret == 0 && span > PAGE_SIZE)
+ ret = __put_user(0, uaddr + size - 1);
return ret;
}
Back to linux.kernel | Previous | Next | Find similar | Unroll thread
[PATCH] mm: tighten fault_in_pages_writeable() Eric Dumazet <eric.dumazet@gmail.com> - 2016-04-26 23:00 +0200
csiph-web