diff options
Diffstat (limited to 'kernel/futex.c')
| -rw-r--r-- | kernel/futex.c | 16 | 
1 files changed, 12 insertions, 4 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index c20f06f38ef3..33664f70e2d2 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -469,7 +469,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)  {  	unsigned long address = (unsigned long)uaddr;  	struct mm_struct *mm = current->mm; -	struct page *page; +	struct page *page, *tail;  	struct address_space *mapping;  	int err, ro = 0; @@ -530,7 +530,15 @@ again:  	 * considered here and page lock forces unnecessarily serialization  	 * From this point on, mapping will be re-verified if necessary and  	 * page lock will be acquired only if it is unavoidable -	 */ +	 * +	 * Mapping checks require the head page for any compound page so the +	 * head page and mapping is looked up now. For anonymous pages, it +	 * does not matter if the page splits in the future as the key is +	 * based on the address. For filesystem-backed pages, the tail is +	 * required as the index of the page determines the key. For +	 * base pages, there is no tail page and tail == page. +	 */ +	tail = page;  	page = compound_head(page);  	mapping = READ_ONCE(page->mapping); @@ -654,7 +662,7 @@ again:  		key->both.offset |= FUT_OFF_INODE; /* inode-based key */  		key->shared.inode = inode; -		key->shared.pgoff = basepage_index(page); +		key->shared.pgoff = basepage_index(tail);  		rcu_read_unlock();  	} @@ -729,7 +737,7 @@ static int get_futex_value_locked(u32 *dest, u32 __user *from)  	int ret;  	pagefault_disable(); -	ret = __copy_from_user_inatomic(dest, from, sizeof(u32)); +	ret = __get_user(*dest, from);  	pagefault_enable();  	return ret ? -EFAULT : 0;  |