All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jakub Kicinski <jakub.kicinski@netronome.com>
To: john.fastabend@gmail.com, alexei.starovoitov@gmail.com,
	daniel@iogearbox.net
Cc: edumazet@google.com, netdev@vger.kernel.org, bpf@vger.kernel.org
Subject: [PATCH bpf v4 06/14] bpf: sockmap, sock_map_delete needs to use xchg
Date: Fri, 19 Jul 2019 10:29:19 -0700	[thread overview]
Message-ID: <20190719172927.18181-7-jakub.kicinski@netronome.com> (raw)
In-Reply-To: <20190719172927.18181-1-jakub.kicinski@netronome.com>

From: John Fastabend <john.fastabend@gmail.com>

__sock_map_delete() may be called from a tcp event such as unhash or
close from the following trace,

  tcp_bpf_close()
    tcp_bpf_remove()
      sk_psock_unlink()
        sock_map_delete_from_link()
          __sock_map_delete()

In this case the sock lock is held but this only protects against
duplicate removals on the TCP side. If the map is free'd then we have
this trace,

  sock_map_free
    xchg()                  <- replaces map entry
    sock_map_unref()
      sk_psock_put()
        sock_map_del_link()

The __sock_map_delete() call however uses a read, test, null over the
map entry which can result in both paths trying to free the map
entry.

To fix use xchg in TCP paths as well so we avoid having two references
to the same map entry.

Fixes: 604326b41a6fb ("bpf, sockmap: convert to generic sk_msg interface")
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
---
 net/core/sock_map.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/net/core/sock_map.c b/net/core/sock_map.c
index 52d4faeee18b..28702f2e9a4a 100644
--- a/net/core/sock_map.c
+++ b/net/core/sock_map.c
@@ -276,16 +276,20 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
 			     struct sock **psk)
 {
 	struct sock *sk;
+	int err = 0;
 
 	raw_spin_lock_bh(&stab->lock);
 	sk = *psk;
 	if (!sk_test || sk_test == sk)
-		*psk = NULL;
+		sk = xchg(psk, NULL);
+
+	if (likely(sk))
+		sock_map_unref(sk, psk);
+	else
+		err = -EINVAL;
+
 	raw_spin_unlock_bh(&stab->lock);
-	if (unlikely(!sk))
-		return -EINVAL;
-	sock_map_unref(sk, psk);
-	return 0;
+	return err;
 }
 
 static void sock_map_delete_from_link(struct bpf_map *map, struct sock *sk,
-- 
2.21.0


  parent reply	other threads:[~2019-07-19 17:31 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-19 17:29 [PATCH bpf v4 00/14] sockmap/tls fixes Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 01/14] net/tls: don't arm strparser immediately in tls_set_sw_offload() Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 02/14] net/tls: don't call tls_sk_proto_close for hw record offload Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 03/14] net/tls: remove close callback sock unlock/lock around TX work flush Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 04/14] net/tls: remove sock unlock/lock around strp_done() Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 05/14] net/tls: fix transition through disconnect with close Jakub Kicinski
2019-07-19 17:29 ` Jakub Kicinski [this message]
2019-07-19 17:29 ` [PATCH bpf v4 07/14] bpf: sockmap, synchronize_rcu before free'ing map Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 08/14] bpf: sockmap, only create entry if ulp is not already enabled Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 09/14] bpf: sockmap/tls, close can race with map free Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 10/14] selftests/tls: add a test for ULP but no keys Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 11/14] selftests/tls: test error codes around TLS ULP installation Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 12/14] selftests/tls: add a bidirectional test Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 13/14] selftests/tls: close the socket with open record Jakub Kicinski
2019-07-19 17:29 ` [PATCH bpf v4 14/14] selftests/tls: add shutdown tests Jakub Kicinski
2019-07-19 17:37 ` [PATCH bpf v4 00/14] sockmap/tls fixes Jakub Kicinski
2019-07-22 14:22   ` Daniel Borkmann
2019-07-22 15:48     ` John Fastabend
2019-07-22 15:46   ` John Fastabend

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=20190719172927.18181-7-jakub.kicinski@netronome.com \
    --to=jakub.kicinski@netronome.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=edumazet@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=netdev@vger.kernel.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 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.