|
@@ -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);
|
|
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)
|
|
static inline int fault_in_pages_writeable(char __user *uaddr, int size)
|
|
{
|
|
{
|
|
- int ret;
|
|
|
|
|
|
+ int span, ret;
|
|
|
|
|
|
if (unlikely(size == 0))
|
|
if (unlikely(size == 0))
|
|
return 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
|
|
* Writing zeroes into userspace here is OK, because we know that if
|
|
* the zero gets there, we'll be overwriting it.
|
|
* the zero gets there, we'll be overwriting it.
|
|
*/
|
|
*/
|
|
ret = __put_user(0, uaddr);
|
|
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;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|