All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
@ 2019-11-06 22:43 Jan Stancek
  2019-11-07 11:11 ` Thomas Gleixner
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jan Stancek @ 2019-11-06 22:43 UTC (permalink / raw)
  To: tglx, mingo; +Cc: peterz, dvhart, longman, linux-kernel, jstancek

Assume following scenario: process A is sleeping on futex (uaddr1)
inside futex_wait(). Process B requeues this waiter via FUTEX_CMP_REQUEUE
to uaddr2, but doesn't wake it up. Later, process A spuriously wakes up
and futex_wait() retries to queue again with same uaddr1/val1:
        if (!signal_pending(current))
                goto retry;

Problem: Userspace fails to wake process A with futex(uaddr2, FUTEX_WAKE)

Store target uaddr/val in futex_requeue() and let futex_wait()
retry after spurious wake up using stored values.

Fixes: d58e6576b0de ("futex: Handle spurious wake up")
Signed-off-by: Jan Stancek <jstancek@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Waiman Long <longman@redhat.com>
---
 kernel/futex.c | 52 +++++++++++++++++++++++++++++++++-------------------
 1 file changed, 33 insertions(+), 19 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index bd18f60e4c6c..c13cfee25d35 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -237,6 +237,9 @@ struct futex_q {
 	struct rt_mutex_waiter *rt_waiter;
 	union futex_key *requeue_pi_key;
 	u32 bitset;
+
+	u32 *uaddr;
+	u32 val;
 } __randomize_layout;
 
 static const struct futex_q futex_q_init = {
@@ -1939,6 +1942,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
 	struct futex_hash_bucket *hb1, *hb2;
 	struct futex_q *this, *next;
 	DEFINE_WAKE_Q(wake_q);
+	u32 curval, targetval;
 
 	if (nr_wake < 0 || nr_requeue < 0)
 		return -EINVAL;
@@ -2005,30 +2009,32 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
 	hb_waiters_inc(hb2);
 	double_lock_hb(hb1, hb2);
 
-	if (likely(cmpval != NULL)) {
-		u32 curval;
-
+	ret = get_futex_value_locked(&targetval, uaddr2);
+	if (!ret && likely(cmpval != NULL))
 		ret = get_futex_value_locked(&curval, uaddr1);
 
-		if (unlikely(ret)) {
-			double_unlock_hb(hb1, hb2);
-			hb_waiters_dec(hb2);
+	if (unlikely(ret)) {
+		double_unlock_hb(hb1, hb2);
+		hb_waiters_dec(hb2);
 
+		ret = get_user(targetval, uaddr2);
+		if (!ret && likely(cmpval != NULL))
 			ret = get_user(curval, uaddr1);
-			if (ret)
-				goto out_put_keys;
 
-			if (!(flags & FLAGS_SHARED))
-				goto retry_private;
+		if (ret)
+			goto out_put_keys;
 
-			put_futex_key(&key2);
-			put_futex_key(&key1);
-			goto retry;
-		}
-		if (curval != *cmpval) {
-			ret = -EAGAIN;
-			goto out_unlock;
-		}
+		if (!(flags & FLAGS_SHARED))
+			goto retry_private;
+
+		put_futex_key(&key2);
+		put_futex_key(&key1);
+		goto retry;
+	}
+
+	if (likely(cmpval != NULL) && (curval != *cmpval)) {
+		ret = -EAGAIN;
+		goto out_unlock;
 	}
 
 	if (requeue_pi && (task_count - nr_wake < nr_requeue)) {
@@ -2185,6 +2191,12 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
 			}
 		}
 		requeue_futex(this, hb1, hb2, &key2);
+		/*
+		 * Save target uaddr/val, in case futex_wait() wakes
+		 * up spuriously and retries to requeue.
+		 */
+		this->uaddr = uaddr2;
+		this->val = targetval;
 		drop_count++;
 	}
 
@@ -2717,6 +2729,8 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
 	if (!bitset)
 		return -EINVAL;
 	q.bitset = bitset;
+	q.uaddr = uaddr;
+	q.val = val;
 
 	to = futex_setup_timer(abs_time, &timeout, flags,
 			       current->timer_slack_ns);
@@ -2725,7 +2739,7 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
 	 * Prepare to wait on uaddr. On success, holds hb lock and increments
 	 * q.key refs.
 	 */
-	ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
+	ret = futex_wait_setup(q.uaddr, q.val, flags, &q, &hb);
 	if (ret)
 		goto out;
 
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
  2019-11-06 22:43 [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup Jan Stancek
@ 2019-11-07 11:11 ` Thomas Gleixner
  2019-11-07 13:16   ` Jan Stancek
  2019-11-08 23:27 ` kbuild test robot
  2019-11-12  2:36 ` kbuild test robot
  2 siblings, 1 reply; 5+ messages in thread
From: Thomas Gleixner @ 2019-11-07 11:11 UTC (permalink / raw)
  To: Jan Stancek; +Cc: Ingo Molnar, Peter Zijlstra, Darren Hart, longman, LKML

Jan!

On Wed, 6 Nov 2019, Jan Stancek wrote:
> Assume following scenario: process A is sleeping on futex (uaddr1)
> inside futex_wait(). Process B requeues this waiter via FUTEX_CMP_REQUEUE
> to uaddr2, but doesn't wake it up. Later, process A spuriously wakes up
> and futex_wait() retries to queue again with same uaddr1/val1:
>         if (!signal_pending(current))
>                 goto retry;

My brain is already wreckaged by staring into futex code for several days
in a row. So it might be just me, but the above qualifies for 'word
salad' as Peter Zijlstra named a similar changelog.

Please try to explain problems in very clear and understandable ways. The
futex code is confusing enough already.

> Problem: Userspace fails to wake process A with futex(uaddr2, FUTEX_WAKE)
> 
> Store target uaddr/val in futex_requeue() and let futex_wait()
> retry after spurious wake up using stored values.

A bit less terse explanations might make the reader actually understand
right away what you are trying to say.

You're describing the WHAT, not the WHY.

> diff --git a/kernel/futex.c b/kernel/futex.c
> index bd18f60e4c6c..c13cfee25d35 100644
> --- a/kernel/futex.c
> +++ b/kernel/futex.c
> @@ -237,6 +237,9 @@ struct futex_q {
>  	struct rt_mutex_waiter *rt_waiter;
>  	union futex_key *requeue_pi_key;
>  	u32 bitset;
> +
> +	u32 *uaddr;
> +	u32 val;
>  } __randomize_layout;
>  
>  static const struct futex_q futex_q_init = {
> @@ -1939,6 +1942,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
>  	struct futex_hash_bucket *hb1, *hb2;
>  	struct futex_q *this, *next;
>  	DEFINE_WAKE_Q(wake_q);
> +	u32 curval, targetval;
>  
>  	if (nr_wake < 0 || nr_requeue < 0)
>  		return -EINVAL;
> @@ -2005,30 +2009,32 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
>  	hb_waiters_inc(hb2);
>  	double_lock_hb(hb1, hb2);
>  
> -	if (likely(cmpval != NULL)) {
> -		u32 curval;
> -
> +	ret = get_futex_value_locked(&targetval, uaddr2);

Storing that value is meaningless as it is subject to change right after
the requeue operation has finished.

Also there is absolutely no requirement for this address to be accessible
at the time of this call. At least not for CMP_REQUEUE, CMP_REQUEUE_PI is a
different case.

> +	if (!ret && likely(cmpval != NULL))
>  		ret = get_futex_value_locked(&curval, uaddr1);
>  
> -		if (unlikely(ret)) {
> -			double_unlock_hb(hb1, hb2);
> -			hb_waiters_dec(hb2);
> +	if (unlikely(ret)) {
> +		double_unlock_hb(hb1, hb2);
> +		hb_waiters_dec(hb2);
>  
> +		ret = get_user(targetval, uaddr2);
> +		if (!ret && likely(cmpval != NULL))
>  			ret = get_user(curval, uaddr1);
> -			if (ret)
> -				goto out_put_keys;
>  
> -			if (!(flags & FLAGS_SHARED))
> -				goto retry_private;
> +		if (ret)
> +			goto out_put_keys;
>  
> -			put_futex_key(&key2);
> -			put_futex_key(&key1);
> -			goto retry;
> -		}
> -		if (curval != *cmpval) {
> -			ret = -EAGAIN;
> -			goto out_unlock;
> -		}
> +		if (!(flags & FLAGS_SHARED))
> +			goto retry_private;
> +
> +		put_futex_key(&key2);
> +		put_futex_key(&key1);
> +		goto retry;
> +	}
> +
> +	if (likely(cmpval != NULL) && (curval != *cmpval)) {
> +		ret = -EAGAIN;
> +		goto out_unlock;
>  	}

I can halfways understand the chunks below this, but the above is
absolutely unclear why this needs to be reshuffled. There is no explanation
whatsoever why that code needs to be changed to achive the below.

This changes the code flow massively and there is absolutely no indication
why this is equivivalent to the previous state.

If at all, and I doubt it, this restructuring wants to be a separate patch.

> @@ -2725,7 +2739,7 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
>  	 * Prepare to wait on uaddr. On success, holds hb lock and increments
>  	 * q.key refs.
>  	 */
> -	ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
> +	ret = futex_wait_setup(q.uaddr, q.val, flags, &q, &hb);
>  	if (ret)
>  		goto out;
>  

So you go great length to "fix" the spurious wakeup case, but what happens if
there is an actual signal?

It will return to handle the signal and then run into the exactly same
situation because it restarts the syscall with the original uaddr1/uval,
right?

That means that the shortcut which was added in commit d58e6576b0de
("futex: Handle spurious wake up") is equivalent to the actual signal case.

So the above churn is pretty pointless because it "fixes" not even half of
the problem and you can't fix the -ERESTARTSYS case at all.

IIRC the uaddr1 value is supposed to change on a requeue operation so that
a late incoming waiter goes back with -EWOULDBLOCK. And excatly the same
would happen on the retry.

Aside of that you are completely failing to explain in which context you
observe this problem. Is that failing on libc, some test case or some other
maybe experimental code?

If there is an actual use case for keeping the uaddr1 value the same across
a requeue then this needs to be described properly and also needs to be
handled differently and consistently in all cases not just for a spurious
wakeup.

But let's talk about that once you came up with a proper explanation for
what you are trying to solve and why you think it's correct.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
  2019-11-07 11:11 ` Thomas Gleixner
@ 2019-11-07 13:16   ` Jan Stancek
  0 siblings, 0 replies; 5+ messages in thread
From: Jan Stancek @ 2019-11-07 13:16 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Ingo Molnar, Peter Zijlstra, Darren Hart, longman, LKML

My apologies for the 'word salad'.

> So you go great length to "fix" the spurious wakeup case, but what happens if
> there is an actual signal?
> 
> It will return to handle the signal and then run into the exactly same
> situation because it restarts the syscall with the original uaddr1/uval,
> right?

Right, I missed that.

> 
> That means that the shortcut which was added in commit d58e6576b0de
> ("futex: Handle spurious wake up") is equivalent to the actual signal case.
> 
> So the above churn is pretty pointless because it "fixes" not even half of
> the problem and you can't fix the -ERESTARTSYS case at all.
> 
> IIRC the uaddr1 value is supposed to change on a requeue operation so that
> a late incoming waiter goes back with -EWOULDBLOCK. And excatly the same
> would happen on the retry.
> 
> Aside of that you are completely failing to explain in which context you
> observe this problem. Is that failing on libc, some test case or some other
> maybe experimental code?

It's test case (LTP futex_cmp_requeue01), which keeps uaddr1 value same
across requeue, and then sporadically fails to wake up some child processes.

> 
> If there is an actual use case for keeping the uaddr1 value the same across
> a requeue..

It seems both I and test author missed some hint at man page
for FUTEX_CMP_REQUEUE and assumed this was valid use case.

> But let's talk about that once you came up with a proper explanation for
> what you are trying to solve and why you think it's correct.

Thank you for the detailed response.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
  2019-11-06 22:43 [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup Jan Stancek
  2019-11-07 11:11 ` Thomas Gleixner
@ 2019-11-08 23:27 ` kbuild test robot
  2019-11-12  2:36 ` kbuild test robot
  2 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2019-11-08 23:27 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 26045 bytes --]

Hi Jan,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on tip/locking/core]
[also build test WARNING on v5.4-rc6 next-20191108]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Jan-Stancek/futex-don-t-retry-futex_wait-with-stale-uaddr-val-after-spurious-wakeup/20191109-055627
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git a0855d24fc22d49cdc25664fb224caee16998683
reproduce: make htmldocs

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   Warning: The Sphinx 'sphinx_rtd_theme' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.
   WARNING: dot(1) not found, for better output quality install graphviz from http://www.graphviz.org
   WARNING: convert(1) not found, for SVG to PDF conversion install ImageMagick (https://www.imagemagick.org)
   include/linux/regulator/machine.h:196: warning: Function parameter or member 'max_uV_step' not described in 'regulation_constraints'
   include/linux/regulator/driver.h:223: warning: Function parameter or member 'resume' not described in 'regulator_ops'
   Error: Cannot open file drivers/dma-buf/reservation.c
   Error: Cannot open file drivers/dma-buf/reservation.c
   Error: Cannot open file drivers/dma-buf/reservation.c
   Error: Cannot open file include/linux/reservation.h
   Error: Cannot open file include/linux/reservation.h
>> kernel/futex.c:244: warning: Function parameter or member 'uaddr' not described in 'futex_q'
>> kernel/futex.c:244: warning: Function parameter or member 'val' not described in 'futex_q'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'quotactl' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'quota_on' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_free_mnt_opts' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_eat_lsm_opts' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_kern_mount' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_show_options' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_add_mnt_opt' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'd_instantiate' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'getprocattr' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'setprocattr' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'locked_down' not described in 'security_list_options'
   include/linux/spi/spi.h:190: warning: Function parameter or member 'driver_override' not described in 'spi_device'
   lib/genalloc.c:1: warning: 'gen_pool_add_virt' not found
   lib/genalloc.c:1: warning: 'gen_pool_alloc' not found
   lib/genalloc.c:1: warning: 'gen_pool_free' not found
   lib/genalloc.c:1: warning: 'gen_pool_alloc_algo' not found
   drivers/gpio/gpiolib-of.c:92: warning: Excess function parameter 'dev' description in 'of_gpio_need_valid_mask'
   include/linux/i2c.h:337: warning: Function parameter or member 'init_irq' not described in 'i2c_client'
   drivers/usb/typec/bus.c:1: warning: 'typec_altmode_unregister_driver' not found
   drivers/usb/typec/bus.c:1: warning: 'typec_altmode_register_driver' not found
   drivers/usb/typec/class.c:1: warning: 'typec_altmode_register_notifier' not found
   drivers/usb/typec/class.c:1: warning: 'typec_altmode_unregister_notifier' not found
   include/linux/w1.h:277: warning: Function parameter or member 'of_match_table' not described in 'w1_family'
   fs/fs-writeback.c:918: warning: Excess function parameter 'nr_pages' description in 'cgroup_writeback_by_id'
   fs/direct-io.c:258: warning: Excess function parameter 'offset' description in 'dio_complete'
   fs/libfs.c:496: warning: Excess function parameter 'available' description in 'simple_write_end'
   fs/posix_acl.c:647: warning: Function parameter or member 'inode' not described in 'posix_acl_update_mode'
   fs/posix_acl.c:647: warning: Function parameter or member 'mode_p' not described in 'posix_acl_update_mode'
   fs/posix_acl.c:647: warning: Function parameter or member 'acl' not described in 'posix_acl_update_mode'
   kernel/dma/coherent.c:1: warning: no structured comments found
   include/linux/input/sparse-keymap.h:43: warning: Function parameter or member 'sw' not described in 'key_entry'
   include/linux/skbuff.h:888: warning: Function parameter or member 'dev_scratch' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'list' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'ip_defrag_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'skb_mstamp_ns' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member '__cloned_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'head_frag' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member '__pkt_type_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'encapsulation' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'encap_hdr_csum' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'csum_valid' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member '__pkt_vlan_present_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'vlan_present' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'csum_complete_sw' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'csum_level' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'inner_protocol_type' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'remcsum_offload' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'sender_cpu' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'reserved_tailroom' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'inner_ipproto' not described in 'sk_buff'
   include/net/sock.h:233: warning: Function parameter or member 'skc_addrpair' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_portpair' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_ipv6only' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_net_refcnt' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_v6_daddr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_v6_rcv_saddr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_cookie' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_listener' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_tw_dr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_rcv_wnd' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_tw_rcv_nxt' not described in 'sock_common'
   include/net/sock.h:515: warning: Function parameter or member 'sk_rx_skb_cache' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_wq_raw' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'tcp_rtx_queue' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_tx_skb_cache' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_route_forced_caps' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_txtime_report_errors' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_validate_xmit_skb' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_bpf_storage' not described in 'sock'
   include/net/sock.h:2439: warning: Function parameter or member 'tcp_rx_skb_cache_key' not described in 'DECLARE_STATIC_KEY_FALSE'
   include/net/sock.h:2439: warning: Excess function parameter 'sk' description in 'DECLARE_STATIC_KEY_FALSE'
   include/net/sock.h:2439: warning: Excess function parameter 'skb' description in 'DECLARE_STATIC_KEY_FALSE'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'gso_partial_features' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'l3mdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xfrmdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'tlsdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'name_assign_type' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'ieee802154_ptr' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'mpls_ptr' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xdp_prog' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'gro_flush_timeout' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'nf_hooks_ingress' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member '____cacheline_aligned_in_smp' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'qdisc_hash' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xps_cpus_map' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xps_rxqs_map' not described in 'net_device'
   include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising' not described in 'phylink_link_state'
   include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising' not described in 'phylink_link_state'
   drivers/net/phy/phylink.c:595: warning: Function parameter or member 'config' not described in 'phylink_create'
   drivers/net/phy/phylink.c:595: warning: Excess function parameter 'ndev' description in 'phylink_create'
   include/linux/bitmap.h:341: warning: Function parameter or member 'nbits' not described in 'bitmap_or_equal'
   include/linux/rculist.h:374: warning: Excess function parameter 'cond' description in 'list_for_each_entry_rcu'
   include/linux/rculist.h:651: warning: Excess function parameter 'cond' description in 'hlist_for_each_entry_rcu'
   mm/util.c:1: warning: 'get_user_pages_fast' not found
   mm/slab.c:4215: warning: Function parameter or member 'objp' not described in '__ksize'
>> kernel/futex.c:244: warning: Function parameter or member 'uaddr' not described in 'futex_q'
>> kernel/futex.c:244: warning: Function parameter or member 'val' not described in 'futex_q'
   drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:335: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
   drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:336: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:142: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_read_lock'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:347: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:348: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:494: warning: Function parameter or member 'start' not described in 'amdgpu_vm_pt_first_dfs'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'adev' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'vm' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'start' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'cursor' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'entry' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:821: warning: Function parameter or member 'level' not described in 'amdgpu_vm_bo_param'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'params' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'bo' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'level' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'pe' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'addr' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'count' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'incr' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'flags' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:2821: warning: Function parameter or member 'pasid' not described in 'amdgpu_vm_make_compute'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:378: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Function parameter or member 'ih' not described in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c:1: warning: no structured comments found
   drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:1: warning: no structured comments found
   drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c:1: warning: 'pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie' not found
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:132: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source @atomic_obj
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:238: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source gpu_info FW provided soc bounding box struct or 0 if not
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'atomic_obj' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'backlight_link' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'backlight_caps' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'freesync_module' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'fw_dmcu' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'dmcu_fw_version' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'soc_bounding_box' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1: warning: 'register_hpd_handlers' not found
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1: warning: 'dm_crtc_high_irq' not found
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1: warning: 'dm_pflip_high_irq' not found
   include/drm/drm_modeset_helper_vtables.h:1053: warning: Function parameter or member 'prepare_writeback_job' not described in 'drm_connector_helper_funcs'
   include/drm/drm_modeset_helper_vtables.h:1053: warning: Function parameter or member 'cleanup_writeback_job' not described in 'drm_connector_helper_funcs'
   include/drm/drm_atomic_state_helper.h:1: warning: no structured comments found
   include/drm/drm_gem_shmem_helper.h:87: warning: Function parameter or member 'madv' not described in 'drm_gem_shmem_object'
   include/drm/drm_gem_shmem_helper.h:87: warning: Function parameter or member 'madv_list' not described in 'drm_gem_shmem_object'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Enum value 'DPLL_ID_TGL_MGPLL5' not described in enum 'intel_dpll_id'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Enum value 'DPLL_ID_TGL_MGPLL6' not described in enum 'intel_dpll_id'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Excess enum value 'DPLL_ID_TGL_TCPLL6' description in 'intel_dpll_id'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Excess enum value 'DPLL_ID_TGL_TCPLL5' description in 'intel_dpll_id'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:342: warning: Function parameter or member 'wakeref' not described in 'intel_shared_dpll'
   Error: Cannot open file drivers/gpu/drm/i915/i915_gem_batch_pool.c
   Error: Cannot open file drivers/gpu/drm/i915/i915_gem_batch_pool.c
   Error: Cannot open file drivers/gpu/drm/i915/i915_gem_batch_pool.c
   drivers/gpu/drm/i915/i915_drv.h:1129: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source The OA context specific information.
   drivers/gpu/drm/i915/i915_drv.h:1143: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source State of the OA buffer.
   drivers/gpu/drm/i915/i915_drv.h:1154: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Locks reads and writes to all head/tail state
   drivers/gpu/drm/i915/i915_drv.h:1176: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source One 'aging' tail pointer and one 'aged' tail pointer ready to
   drivers/gpu/drm/i915/i915_drv.h:1188: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Index for the aged tail ready to read() data up to.
   drivers/gpu/drm/i915/i915_drv.h:1193: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source A monotonic timestamp for when the current aging tail pointer
   drivers/gpu/drm/i915/i915_drv.h:1199: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Although we can always read back the head pointer register,
   drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'pinned_ctx' not described in 'i915_perf_stream'
   drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'specific_ctx_id' not described in 'i915_perf_stream'
   drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'specific_ctx_id_mask' not described in 'i915_perf_stream'
   drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'poll_check_timer' not described in 'i915_perf_stream'
   drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'poll_wq' not described in 'i915_perf_stream'
   drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'pollin' not described in 'i915_perf_stream'
   drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'periodic' not described in 'i915_perf_stream'
   drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'period_exponent' not described in 'i915_perf_stream'
   drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'oa_buffer' not described in 'i915_perf_stream'
   drivers/gpu/drm/i915/i915_drv.h:1129: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source The OA context specific information.
   drivers/gpu/drm/i915/i915_drv.h:1143: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source State of the OA buffer.
   drivers/gpu/drm/i915/i915_drv.h:1154: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Locks reads and writes to all head/tail state
   drivers/gpu/drm/i915/i915_drv.h:1176: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source One 'aging' tail pointer and one 'aged' tail pointer ready to
   drivers/gpu/drm/i915/i915_drv.h:1188: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Index for the aged tail ready to read() data up to.
   drivers/gpu/drm/i915/i915_drv.h:1193: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source A monotonic timestamp for when the current aging tail pointer
   drivers/gpu/drm/i915/i915_drv.h:1199: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Although we can always read back the head pointer register,
   drivers/gpu/drm/i915/i915_drv.h:1129: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source The OA context specific information.
   drivers/gpu/drm/i915/i915_drv.h:1143: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source State of the OA buffer.
   drivers/gpu/drm/i915/i915_drv.h:1154: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Locks reads and writes to all head/tail state
   drivers/gpu/drm/i915/i915_drv.h:1176: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source One 'aging' tail pointer and one 'aged' tail pointer ready to
   drivers/gpu/drm/i915/i915_drv.h:1188: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Index for the aged tail ready to read() data up to.
   drivers/gpu/drm/i915/i915_drv.h:1193: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source A monotonic timestamp for when the current aging tail pointer
   drivers/gpu/drm/i915/i915_drv.h:1199: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Although we can always read back the head pointer register,
   drivers/gpu/drm/mcde/mcde_drv.c:1: warning: 'ST-Ericsson MCDE DRM Driver' not found
   include/net/cfg80211.h:1185: warning: Function parameter or member 'txpwr' not described in 'station_parameters'
   include/net/mac80211.h:4056: warning: Function parameter or member 'sta_set_txpwr' not described in 'ieee80211_ops'
   include/net/mac80211.h:2018: warning: Function parameter or member 'txpwr' not described in 'ieee80211_sta'
   Documentation/admin-guide/perf/imx-ddr.rst:21: WARNING: Unexpected indentation.
   Documentation/admin-guide/perf/imx-ddr.rst:34: WARNING: Unexpected indentation.
   Documentation/admin-guide/perf/imx-ddr.rst:40: WARNING: Unexpected indentation.
   Documentation/admin-guide/perf/imx-ddr.rst:45: WARNING: Unexpected indentation.
   Documentation/admin-guide/perf/imx-ddr.rst:52: WARNING: Unexpected indentation.
   Documentation/hwmon/inspur-ipsps1.rst:2: WARNING: Title underline too short.

vim +244 kernel/futex.c

^1da177e4c3f41 Linus Torvalds 2005-04-16 @244  

:::::: The code at line 244 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2

:::::: TO: Linus Torvalds <torvalds@ppc970.osdl.org>
:::::: CC: Linus Torvalds <torvalds@ppc970.osdl.org>

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org Intel Corporation

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 7279 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
  2019-11-06 22:43 [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup Jan Stancek
  2019-11-07 11:11 ` Thomas Gleixner
  2019-11-08 23:27 ` kbuild test robot
@ 2019-11-12  2:36 ` kbuild test robot
  2 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2019-11-12  2:36 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 14704 bytes --]

Hi Jan,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on tip/locking/core]
[cannot apply to v5.4-rc7 next-20191111]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Jan-Stancek/futex-don-t-retry-futex_wait-with-stale-uaddr-val-after-spurious-wakeup/20191109-055627
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git a0855d24fc22d49cdc25664fb224caee16998683
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.1-29-g781bc5d-dirty
        make ARCH=x86_64 allmodconfig
        make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)

>> kernel/futex.c:2198:29: sparse: sparse: incorrect type in assignment (different address spaces) @@    expected unsigned int [usertype] *uaddr @@    got unsigned int [nodeunsigned int [usertype] *uaddr @@
>> kernel/futex.c:2198:29: sparse:    expected unsigned int [usertype] *uaddr
>> kernel/futex.c:2198:29: sparse:    got unsigned int [noderef] [usertype] <asn:1> *uaddr2
>> kernel/futex.c:2732:17: sparse: sparse: incorrect type in assignment (different address spaces) @@    expected unsigned int [usertype] *[assigned] uaddr @@    got unsigneunsigned int [usertype] *[assigned] uaddr @@
>> kernel/futex.c:2732:17: sparse:    expected unsigned int [usertype] *[assigned] uaddr
>> kernel/futex.c:2732:17: sparse:    got unsigned int [noderef] [usertype] <asn:1> *uaddr
>> kernel/futex.c:2742:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@    expected unsigned int [noderef] [usertype] <asn:1> *uaddr @@    got d int [noderef] [usertype] <asn:1> *uaddr @@
>> kernel/futex.c:2742:33: sparse:    expected unsigned int [noderef] [usertype] <asn:1> *uaddr
>> kernel/futex.c:2742:33: sparse:    got unsigned int [usertype] *[assigned] uaddr
   kernel/futex.c:1562:9: sparse: sparse: context imbalance in 'wake_futex_pi' - unexpected unlock
   kernel/futex.c:1722:33: sparse: sparse: context imbalance in 'futex_wake_op' - different lock contexts for basic block
   include/linux/kasan-checks.h:38:20: sparse: sparse: context imbalance in 'futex_requeue' - different lock contexts for basic block
   kernel/futex.c:2503:9: sparse: sparse: context imbalance in 'fixup_pi_state_owner' - unexpected unlock
   kernel/futex.c:2612:13: sparse: sparse: context imbalance in 'futex_wait_queue_me' - unexpected unlock
   kernel/futex.c:2714:1: sparse: sparse: context imbalance in 'futex_wait_setup' - different lock contexts for basic block
   kernel/futex.c:2995:12: sparse: sparse: context imbalance in 'futex_unlock_pi' - different lock contexts for basic block
   kernel/futex.c:3273:29: sparse: sparse: context imbalance in 'futex_wait_requeue_pi' - unexpected unlock

vim +2198 kernel/futex.c

  1916	
  1917	/**
  1918	 * futex_requeue() - Requeue waiters from uaddr1 to uaddr2
  1919	 * @uaddr1:	source futex user address
  1920	 * @flags:	futex flags (FLAGS_SHARED, etc.)
  1921	 * @uaddr2:	target futex user address
  1922	 * @nr_wake:	number of waiters to wake (must be 1 for requeue_pi)
  1923	 * @nr_requeue:	number of waiters to requeue (0-INT_MAX)
  1924	 * @cmpval:	@uaddr1 expected value (or %NULL)
  1925	 * @requeue_pi:	if we are attempting to requeue from a non-pi futex to a
  1926	 *		pi futex (pi to pi requeue is not supported)
  1927	 *
  1928	 * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
  1929	 * uaddr2 atomically on behalf of the top waiter.
  1930	 *
  1931	 * Return:
  1932	 *  - >=0 - on success, the number of tasks requeued or woken;
  1933	 *  -  <0 - on error
  1934	 */
  1935	static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
  1936				 u32 __user *uaddr2, int nr_wake, int nr_requeue,
  1937				 u32 *cmpval, int requeue_pi)
  1938	{
  1939		union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
  1940		int drop_count = 0, task_count = 0, ret;
  1941		struct futex_pi_state *pi_state = NULL;
  1942		struct futex_hash_bucket *hb1, *hb2;
  1943		struct futex_q *this, *next;
  1944		DEFINE_WAKE_Q(wake_q);
  1945		u32 curval, targetval;
  1946	
  1947		if (nr_wake < 0 || nr_requeue < 0)
  1948			return -EINVAL;
  1949	
  1950		/*
  1951		 * When PI not supported: return -ENOSYS if requeue_pi is true,
  1952		 * consequently the compiler knows requeue_pi is always false past
  1953		 * this point which will optimize away all the conditional code
  1954		 * further down.
  1955		 */
  1956		if (!IS_ENABLED(CONFIG_FUTEX_PI) && requeue_pi)
  1957			return -ENOSYS;
  1958	
  1959		if (requeue_pi) {
  1960			/*
  1961			 * Requeue PI only works on two distinct uaddrs. This
  1962			 * check is only valid for private futexes. See below.
  1963			 */
  1964			if (uaddr1 == uaddr2)
  1965				return -EINVAL;
  1966	
  1967			/*
  1968			 * requeue_pi requires a pi_state, try to allocate it now
  1969			 * without any locks in case it fails.
  1970			 */
  1971			if (refill_pi_state_cache())
  1972				return -ENOMEM;
  1973			/*
  1974			 * requeue_pi must wake as many tasks as it can, up to nr_wake
  1975			 * + nr_requeue, since it acquires the rt_mutex prior to
  1976			 * returning to userspace, so as to not leave the rt_mutex with
  1977			 * waiters and no owner.  However, second and third wake-ups
  1978			 * cannot be predicted as they involve race conditions with the
  1979			 * first wake and a fault while looking up the pi_state.  Both
  1980			 * pthread_cond_signal() and pthread_cond_broadcast() should
  1981			 * use nr_wake=1.
  1982			 */
  1983			if (nr_wake != 1)
  1984				return -EINVAL;
  1985		}
  1986	
  1987	retry:
  1988		ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, FUTEX_READ);
  1989		if (unlikely(ret != 0))
  1990			goto out;
  1991		ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2,
  1992				    requeue_pi ? FUTEX_WRITE : FUTEX_READ);
  1993		if (unlikely(ret != 0))
  1994			goto out_put_key1;
  1995	
  1996		/*
  1997		 * The check above which compares uaddrs is not sufficient for
  1998		 * shared futexes. We need to compare the keys:
  1999		 */
  2000		if (requeue_pi && match_futex(&key1, &key2)) {
  2001			ret = -EINVAL;
  2002			goto out_put_keys;
  2003		}
  2004	
  2005		hb1 = hash_futex(&key1);
  2006		hb2 = hash_futex(&key2);
  2007	
  2008	retry_private:
  2009		hb_waiters_inc(hb2);
  2010		double_lock_hb(hb1, hb2);
  2011	
  2012		ret = get_futex_value_locked(&targetval, uaddr2);
  2013		if (!ret && likely(cmpval != NULL))
  2014			ret = get_futex_value_locked(&curval, uaddr1);
  2015	
  2016		if (unlikely(ret)) {
  2017			double_unlock_hb(hb1, hb2);
  2018			hb_waiters_dec(hb2);
  2019	
  2020			ret = get_user(targetval, uaddr2);
  2021			if (!ret && likely(cmpval != NULL))
  2022				ret = get_user(curval, uaddr1);
  2023	
  2024			if (ret)
  2025				goto out_put_keys;
  2026	
  2027			if (!(flags & FLAGS_SHARED))
  2028				goto retry_private;
  2029	
  2030			put_futex_key(&key2);
  2031			put_futex_key(&key1);
  2032			goto retry;
  2033		}
  2034	
  2035		if (likely(cmpval != NULL) && (curval != *cmpval)) {
  2036			ret = -EAGAIN;
  2037			goto out_unlock;
  2038		}
  2039	
  2040		if (requeue_pi && (task_count - nr_wake < nr_requeue)) {
  2041			/*
  2042			 * Attempt to acquire uaddr2 and wake the top waiter. If we
  2043			 * intend to requeue waiters, force setting the FUTEX_WAITERS
  2044			 * bit.  We force this here where we are able to easily handle
  2045			 * faults rather in the requeue loop below.
  2046			 */
  2047			ret = futex_proxy_trylock_atomic(uaddr2, hb1, hb2, &key1,
  2048							 &key2, &pi_state, nr_requeue);
  2049	
  2050			/*
  2051			 * At this point the top_waiter has either taken uaddr2 or is
  2052			 * waiting on it.  If the former, then the pi_state will not
  2053			 * exist yet, look it up one more time to ensure we have a
  2054			 * reference to it. If the lock was taken, ret contains the
  2055			 * vpid of the top waiter task.
  2056			 * If the lock was not taken, we have pi_state and an initial
  2057			 * refcount on it. In case of an error we have nothing.
  2058			 */
  2059			if (ret > 0) {
  2060				WARN_ON(pi_state);
  2061				drop_count++;
  2062				task_count++;
  2063				/*
  2064				 * If we acquired the lock, then the user space value
  2065				 * of uaddr2 should be vpid. It cannot be changed by
  2066				 * the top waiter as it is blocked on hb2 lock if it
  2067				 * tries to do so. If something fiddled with it behind
  2068				 * our back the pi state lookup might unearth it. So
  2069				 * we rather use the known value than rereading and
  2070				 * handing potential crap to lookup_pi_state.
  2071				 *
  2072				 * If that call succeeds then we have pi_state and an
  2073				 * initial refcount on it.
  2074				 */
  2075				ret = lookup_pi_state(uaddr2, ret, hb2, &key2, &pi_state);
  2076			}
  2077	
  2078			switch (ret) {
  2079			case 0:
  2080				/* We hold a reference on the pi state. */
  2081				break;
  2082	
  2083				/* If the above failed, then pi_state is NULL */
  2084			case -EFAULT:
  2085				double_unlock_hb(hb1, hb2);
  2086				hb_waiters_dec(hb2);
  2087				put_futex_key(&key2);
  2088				put_futex_key(&key1);
  2089				ret = fault_in_user_writeable(uaddr2);
  2090				if (!ret)
  2091					goto retry;
  2092				goto out;
  2093			case -EAGAIN:
  2094				/*
  2095				 * Two reasons for this:
  2096				 * - Owner is exiting and we just wait for the
  2097				 *   exit to complete.
  2098				 * - The user space value changed.
  2099				 */
  2100				double_unlock_hb(hb1, hb2);
  2101				hb_waiters_dec(hb2);
  2102				put_futex_key(&key2);
  2103				put_futex_key(&key1);
  2104				cond_resched();
  2105				goto retry;
  2106			default:
  2107				goto out_unlock;
  2108			}
  2109		}
  2110	
  2111		plist_for_each_entry_safe(this, next, &hb1->chain, list) {
  2112			if (task_count - nr_wake >= nr_requeue)
  2113				break;
  2114	
  2115			if (!match_futex(&this->key, &key1))
  2116				continue;
  2117	
  2118			/*
  2119			 * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always
  2120			 * be paired with each other and no other futex ops.
  2121			 *
  2122			 * We should never be requeueing a futex_q with a pi_state,
  2123			 * which is awaiting a futex_unlock_pi().
  2124			 */
  2125			if ((requeue_pi && !this->rt_waiter) ||
  2126			    (!requeue_pi && this->rt_waiter) ||
  2127			    this->pi_state) {
  2128				ret = -EINVAL;
  2129				break;
  2130			}
  2131	
  2132			/*
  2133			 * Wake nr_wake waiters.  For requeue_pi, if we acquired the
  2134			 * lock, we already woke the top_waiter.  If not, it will be
  2135			 * woken by futex_unlock_pi().
  2136			 */
  2137			if (++task_count <= nr_wake && !requeue_pi) {
  2138				mark_wake_futex(&wake_q, this);
  2139				continue;
  2140			}
  2141	
  2142			/* Ensure we requeue to the expected futex for requeue_pi. */
  2143			if (requeue_pi && !match_futex(this->requeue_pi_key, &key2)) {
  2144				ret = -EINVAL;
  2145				break;
  2146			}
  2147	
  2148			/*
  2149			 * Requeue nr_requeue waiters and possibly one more in the case
  2150			 * of requeue_pi if we couldn't acquire the lock atomically.
  2151			 */
  2152			if (requeue_pi) {
  2153				/*
  2154				 * Prepare the waiter to take the rt_mutex. Take a
  2155				 * refcount on the pi_state and store the pointer in
  2156				 * the futex_q object of the waiter.
  2157				 */
  2158				get_pi_state(pi_state);
  2159				this->pi_state = pi_state;
  2160				ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
  2161								this->rt_waiter,
  2162								this->task);
  2163				if (ret == 1) {
  2164					/*
  2165					 * We got the lock. We do neither drop the
  2166					 * refcount on pi_state nor clear
  2167					 * this->pi_state because the waiter needs the
  2168					 * pi_state for cleaning up the user space
  2169					 * value. It will drop the refcount after
  2170					 * doing so.
  2171					 */
  2172					requeue_pi_wake_futex(this, &key2, hb2);
  2173					drop_count++;
  2174					continue;
  2175				} else if (ret) {
  2176					/*
  2177					 * rt_mutex_start_proxy_lock() detected a
  2178					 * potential deadlock when we tried to queue
  2179					 * that waiter. Drop the pi_state reference
  2180					 * which we took above and remove the pointer
  2181					 * to the state from the waiters futex_q
  2182					 * object.
  2183					 */
  2184					this->pi_state = NULL;
  2185					put_pi_state(pi_state);
  2186					/*
  2187					 * We stop queueing more waiters and let user
  2188					 * space deal with the mess.
  2189					 */
  2190					break;
  2191				}
  2192			}
  2193			requeue_futex(this, hb1, hb2, &key2);
  2194			/*
  2195			 * Save target uaddr/val, in case futex_wait() wakes
  2196			 * up spuriously and retries to requeue.
  2197			 */
> 2198			this->uaddr = uaddr2;
  2199			this->val = targetval;
  2200			drop_count++;
  2201		}
  2202	
  2203		/*
  2204		 * We took an extra initial reference to the pi_state either
  2205		 * in futex_proxy_trylock_atomic() or in lookup_pi_state(). We
  2206		 * need to drop it here again.
  2207		 */
  2208		put_pi_state(pi_state);
  2209	
  2210	out_unlock:
  2211		double_unlock_hb(hb1, hb2);
  2212		wake_up_q(&wake_q);
  2213		hb_waiters_dec(hb2);
  2214	
  2215		/*
  2216		 * drop_futex_key_refs() must be called outside the spinlocks. During
  2217		 * the requeue we moved futex_q's from the hash bucket at key1 to the
  2218		 * one at key2 and updated their key pointer.  We no longer need to
  2219		 * hold the references to key1.
  2220		 */
  2221		while (--drop_count >= 0)
  2222			drop_futex_key_refs(&key1);
  2223	
  2224	out_put_keys:
  2225		put_futex_key(&key2);
  2226	out_put_key1:
  2227		put_futex_key(&key1);
  2228	out:
  2229		return ret ? ret : task_count;
  2230	}
  2231	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org Intel Corporation

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-11-12  2:36 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-06 22:43 [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup Jan Stancek
2019-11-07 11:11 ` Thomas Gleixner
2019-11-07 13:16   ` Jan Stancek
2019-11-08 23:27 ` kbuild test robot
2019-11-12  2:36 ` kbuild test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.