4.18-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Björn Töpel <[email protected]>

[ Upstream commit cee271678d0e3177a25d0fcb2fa5e051d48e4262 ]

The XSKMAP update and delete functions called synchronize_net(), which
can sleep. It is not allowed to sleep during an RCU read section.

Instead we need to make sure that the sock sk_destruct (xsk_destruct)
function is asynchronously called after an RCU grace period. Setting
the SOCK_RCU_FREE flag for XDP sockets takes care of this.

Fixes: fbfc504a24f5 ("bpf: introduce new bpf AF_XDP map type 
BPF_MAP_TYPE_XSKMAP")
Reported-by: Eric Dumazet <[email protected]>
Signed-off-by: Björn Töpel <[email protected]>
Acked-by: Song Liu <[email protected]>
Signed-off-by: Daniel Borkmann <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
 kernel/bpf/xskmap.c |   10 ++--------
 net/xdp/xsk.c       |    2 ++
 2 files changed, 4 insertions(+), 8 deletions(-)

--- a/kernel/bpf/xskmap.c
+++ b/kernel/bpf/xskmap.c
@@ -191,11 +191,8 @@ static int xsk_map_update_elem(struct bp
        sock_hold(sock->sk);
 
        old_xs = xchg(&m->xsk_map[i], xs);
-       if (old_xs) {
-               /* Make sure we've flushed everything. */
-               synchronize_net();
+       if (old_xs)
                sock_put((struct sock *)old_xs);
-       }
 
        sockfd_put(sock);
        return 0;
@@ -211,11 +208,8 @@ static int xsk_map_delete_elem(struct bp
                return -EINVAL;
 
        old_xs = xchg(&m->xsk_map[k], NULL);
-       if (old_xs) {
-               /* Make sure we've flushed everything. */
-               synchronize_net();
+       if (old_xs)
                sock_put((struct sock *)old_xs);
-       }
 
        return 0;
 }
--- a/net/xdp/xsk.c
+++ b/net/xdp/xsk.c
@@ -744,6 +744,8 @@ static int xsk_create(struct net *net, s
        sk->sk_destruct = xsk_destruct;
        sk_refcnt_debug_inc(sk);
 
+       sock_set_flag(sk, SOCK_RCU_FREE);
+
        xs = xdp_sk(sk);
        mutex_init(&xs->mutex);
        spin_lock_init(&xs->tx_completion_lock);


Reply via email to