]> www.infradead.org Git - users/dwmw2/linux.git/commit
bpf: sockmap, sock_map_delete needs to use xchg
authorJohn Fastabend <john.fastabend@gmail.com>
Fri, 19 Jul 2019 17:29:19 +0000 (10:29 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Aug 2019 06:29:54 +0000 (08:29 +0200)
commit2a574254d6f59b4e5f64277712c2480e74ef1bc6
tree7a3605da2b142a3e2702ad2308dcdb413baed282
parent705409085597200cfd027c37c19b0fb6b5d2cdc9
bpf: sockmap, sock_map_delete needs to use xchg

[ Upstream commit 45a4521dcbd92e71c9e53031b40e34211d3b4feb ]

__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>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/core/sock_map.c