mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Paolo Abeni <pabeni@redhat.com>
To: Kuniyuki Iwashima <kuniyu@amazon.com>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>,
	Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>,
	David Ahern <dsahern@kernel.org>,
	Martin KaFai Lau <martin.lau@kernel.org>
Cc: Craig Gallek <kraig@google.com>,
	Willem de Bruijn <willemb@google.com>,
	Kuniyuki Iwashima <kuni1840@gmail.com>,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v1 net 1/3] udp: Update reuse->has_conns under reuseport_lock.
Date: Tue, 11 Oct 2022 12:50:52 +0200	[thread overview]
Message-ID: <468f01fc1dde6cf44fab51653eeb626fc8521db2.camel@redhat.com> (raw)
In-Reply-To: <20221010174351.11024-2-kuniyu@amazon.com>

On Mon, 2022-10-10 at 10:43 -0700, Kuniyuki Iwashima wrote:
> When we call connect() for a UDP socket in a reuseport group, we have
> to update sk->sk_reuseport_cb->has_conns to 1.  Otherwise, the kernel
> could select a unconnected socket wrongly for packets sent to the
> connected socket.
> 
> However, the current way to set has_conns is illegal and possible to
> trigger that problem.  reuseport_has_conns() changes has_conns under
> rcu_read_lock(), which upgrades the RCU reader to the updater.  Then,
> it must do the update under the updater's lock, reuseport_lock, but
> it doesn't for now.
> 
> For this reason, there is a race below where we fail to set has_conns
> resulting in the wrong socket selection.  To avoid the race, let's split
> the reader and updater with proper locking.
> 
>  cpu1                               cpu2
> +----+                             +----+
> 
> __ip[46]_datagram_connect()        reuseport_grow()
> .                                  .
> > - reuseport_has_conns(sk, true)   |- more_reuse = __reuseport_alloc(more_socks_size)
> >  .                               |
> >  |- rcu_read_lock()
> >  |- reuse = rcu_dereference(sk->sk_reuseport_cb)
> >  |
> >  |                               |  /* reuse->has_conns == 0 here */
> >  |                               |- more_reuse->has_conns = reuse->has_conns
> >  |- reuse->has_conns = 1         |  /* more_reuse->has_conns SHOULD BE 1 HERE */
> >  |                               |
> >  |                               |- rcu_assign_pointer(reuse->socks[i]->sk_reuseport_cb,
> >  |                               |                     more_reuse)
> >  `- rcu_read_unlock()            `- kfree_rcu(reuse, rcu)
> > 
> > - sk->sk_state = TCP_ESTABLISHED
> 
> Fixes: acdcecc61285 ("udp: correct reuseport selection with connected sockets")
> Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
> ---
>  include/net/sock_reuseport.h | 23 +++++++++++++++++------
>  net/ipv4/datagram.c          |  2 +-
>  net/ipv4/udp.c               |  2 +-
>  net/ipv6/datagram.c          |  2 +-
>  net/ipv6/udp.c               |  2 +-
>  5 files changed, 21 insertions(+), 10 deletions(-)
> 
> diff --git a/include/net/sock_reuseport.h b/include/net/sock_reuseport.h
> index 473b0b0fa4ab..fe9779e6d90f 100644
> --- a/include/net/sock_reuseport.h
> +++ b/include/net/sock_reuseport.h
> @@ -43,21 +43,32 @@ struct sock *reuseport_migrate_sock(struct sock *sk,
>  extern int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog);
>  extern int reuseport_detach_prog(struct sock *sk);
>  
> -static inline bool reuseport_has_conns(struct sock *sk, bool set)
> +static inline bool reuseport_has_conns(struct sock *sk)
>  {
>  	struct sock_reuseport *reuse;
>  	bool ret = false;
>  
>  	rcu_read_lock();
>  	reuse = rcu_dereference(sk->sk_reuseport_cb);
> -	if (reuse) {
> -		if (set)
> -			reuse->has_conns = 1;
> -		ret = reuse->has_conns;
> -	}
> +	if (reuse && reuse->has_conns)
> +		ret = true;
>  	rcu_read_unlock();
>  
>  	return ret;
>  }
>  
> +static inline void reuseport_has_conns_set(struct sock *sk)
> +{
> +	struct sock_reuseport *reuse;
> +
> +	if (!rcu_access_pointer(sk->sk_reuseport_cb))
> +		return;
> +
> +	spin_lock(&reuseport_lock);
> +	reuse = rcu_dereference_protected(sk->sk_reuseport_cb,
> +					  lockdep_is_held(&reuseport_lock));
> +	reuse->has_conns = 1;
> +	spin_unlock(&reuseport_lock);
> +}

Since the above is not super critical, it's probably better move it
into  sock_reuseport.c file and export it (to fix the build issue)

Cheers,

Paolo


  parent reply	other threads:[~2022-10-11 10:51 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-10 17:43 [PATCH v1 net 0/3] soreuseport: Fix issues related to the faster selection algorithm Kuniyuki Iwashima
2022-10-10 17:43 ` [PATCH v1 net 1/3] udp: Update reuse->has_conns under reuseport_lock Kuniyuki Iwashima
2022-10-11  1:43   ` kernel test robot
2022-10-11 10:50   ` Paolo Abeni [this message]
2022-10-11 15:16     ` Kuniyuki Iwashima
2022-10-10 17:43 ` [PATCH v1 net 2/3] soreuseport: Fix socket selection for SO_INCOMING_CPU Kuniyuki Iwashima
2022-10-11 11:28   ` Paolo Abeni
2022-10-11 15:19     ` Kuniyuki Iwashima
2022-10-10 17:43 ` [PATCH v1 net 3/3] selftest: Add test " Kuniyuki Iwashima
2022-10-11 11:34   ` Paolo Abeni
2022-10-11 15:21     ` Kuniyuki Iwashima

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=468f01fc1dde6cf44fab51653eeb626fc8521db2.camel@redhat.com \
    --to=pabeni@redhat.com \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=kraig@google.com \
    --cc=kuba@kernel.org \
    --cc=kuni1840@gmail.com \
    --cc=kuniyu@amazon.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=martin.lau@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=willemb@google.com \
    --cc=yoshfuji@linux-ipv6.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome