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>
This commit is contained in:
parent
297880f4af
commit
b8ca9e3a61
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue