Patch "fix fault_in_multipages_...() on architectures with no-op access_ok()" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
fix fault_in_multipages_...() on architectures with no-op access_ok()
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
fix-fault_in_multipages_...-on-architectures-with-no-op-access_ok.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
e23d4159b109167126e5bcd7f3775c95de7fee47Mon Sep 17 00:00:00 2001
From: Al Viro <[email protected]>
Date: Tue, 20 Sep 2016 20:07:42 +0100
Subject: fix fault_in_multipages_...() on architectures with no-op access_ok()
From: Al Viro <[email protected]>
commit e23d4159b109167126e5bcd7f3775c95de7fee47 upstream.
Switching iov_iter fault-in to multipages variants has exposed an old bug in underlying fault_in_multipages_...(); they break if the range passed to them wraps around. Normally access_ok() done by callers will prevent such (and it's a guaranteed EFAULT - ERR_PTR() values fall into such a range and they should not point to any valid objects).
However, on architectures where userland and kernel live in different MMU contexts (e.g. s390) access_ok() is a no-op and on those a range with a wraparound can reach fault_in_multipages_...().
Since any wraparound means EFAULT there, the fix is trivial - turn those
while (uaddr <= end)
...
into
if (unlikely(uaddr > end))
return -EFAULT;
do
...
while (uaddr <= end);--- include/linux/pagemap.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-)
include/linux/pagemap.h +19 -19
@@ -601,56 +601,56 @@ static inline int fault_in_pages_readabl*/ static inline int fault_in_multipages_writeable (char __user *uaddr,int size) { -int ret =0 ;char __user *end = uaddr + size -1 ;if (unlikely (size ==0 )) -return ret; +return 0 ; +if (unlikely (uaddr > end)) +return -EFAULT ;/* * Writing zeroes into userspace here is OK, because we know that if * the zero gets there, we'll be overwriting it. */ -while (uaddr <= end) { - ret =__put_user (0 , uaddr); -if (ret !=0 ) -return ret; +do { +if (unlikely (__put_user (0 , uaddr) !=0 )) +return -EFAULT ; uaddr +=PAGE_SIZE ; - } + }while (uaddr <= end);/* Check whether the range spilled into the next page. */ if (((unsigned long )uaddr &PAGE_MASK ) == ((unsigned long )end &PAGE_MASK )) - ret =__put_user (0 , end); +return __put_user (0 , end); -return ret; +return 0 ; }static inline int fault_in_multipages_readable (const char __user *uaddr,int size) {volatile char c; -int ret =0 ;const char __user *end = uaddr + size -1 ;if (unlikely (size ==0 )) -return ret; +return 0 ; + +if (unlikely (uaddr > end)) +return -EFAULT ; -while (uaddr <= end) { - ret =__get_user (c, uaddr); -if (ret !=0 ) -return ret; +do { +if (unlikely (__get_user (c, uaddr) !=0 )) +return -EFAULT ; uaddr +=PAGE_SIZE ; - } + }while (uaddr <= end);/* Check whether the range spilled into the next page. */ if (((unsigned long )uaddr &PAGE_MASK ) == ((unsigned long )end &PAGE_MASK )) { - ret =__get_user (c, end); - (void )c; +return __get_user (c, end); } -return ret; +return 0 ; } int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/fix-fault_in_multipages_...-on-architectures-with-no-op-access_ok.patch queue-4.4/tracing-move-mutex-to-protect-against-resetting-of-seq-data.patch