bpf: net: Add SO_DETACH_REUSEPORT_BPF
authorMartin KaFai Lau <kafai@fb.com>
Thu, 13 Jun 2019 22:00:01 +0000 (15:00 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Fri, 14 Jun 2019 23:21:19 +0000 (01:21 +0200)
There is SO_ATTACH_REUSEPORT_[CE]BPF but there is no DETACH.
This patch adds SO_DETACH_REUSEPORT_BPF sockopt.  The same
sockopt can be used to undo both SO_ATTACH_REUSEPORT_[CE]BPF.

reseport_detach_prog() is added and it is mostly a mirror
of the existing reuseport_attach_prog().  The differences are,
it does not call reuseport_alloc() and returns -ENOENT when
there is no old prog.

Cc: Craig Gallek <kraig@google.com>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Reviewed-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
arch/alpha/include/uapi/asm/socket.h
arch/mips/include/uapi/asm/socket.h
arch/parisc/include/uapi/asm/socket.h
arch/sparc/include/uapi/asm/socket.h
include/net/sock_reuseport.h
include/uapi/asm-generic/socket.h
net/core/sock.c
net/core/sock_reuseport.c

index 976e89b116e5b5747d1e282b748befefd3634cdf..de6c4df610826c262fadadfb5133ada318d2c2bd 100644 (file)
 #define SO_RCVTIMEO_NEW         66
 #define SO_SNDTIMEO_NEW         67
 
+#define SO_DETACH_REUSEPORT_BPF 68
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64
index d41765cfbc6ebae8af75fc892c7ac2e71c301393..d0a9ed2ca2d6831856daedb3275e7d0a841209a0 100644 (file)
 #define SO_RCVTIMEO_NEW         66
 #define SO_SNDTIMEO_NEW         67
 
+#define SO_DETACH_REUSEPORT_BPF 68
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64
index 66c5dd245ac7551dcccdcfeb204d2aa5d675c41e..10173c32195e4cdd75b7436ea5ef19ff2cfa0644 100644 (file)
 #define SO_RCVTIMEO_NEW         0x4040
 #define SO_SNDTIMEO_NEW         0x4041
 
+#define SO_DETACH_REUSEPORT_BPF 0x4042
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64
index 9265a9eece15f498563eb658001aa41ac4d0f756..8029b681fc7ca142155666008eebaaf44262f541 100644 (file)
 #define SO_RCVTIMEO_NEW          0x0044
 #define SO_SNDTIMEO_NEW          0x0045
 
+#define SO_DETACH_REUSEPORT_BPF  0x0047
+
 #if !defined(__KERNEL__)
 
 
index 8a5f70c7cdf24b08d863b79afe5bdc7710e6d88f..d9112de852614ebaa07e4e584e2782c2706458c4 100644 (file)
@@ -35,6 +35,8 @@ extern struct sock *reuseport_select_sock(struct sock *sk,
                                          struct sk_buff *skb,
                                          int hdr_len);
 extern int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog);
+extern int reuseport_detach_prog(struct sock *sk);
+
 int reuseport_get_id(struct sock_reuseport *reuse);
 
 #endif  /* _SOCK_REUSEPORT_H */
index 8c1391c89171aa8d6b3ef253e2fb4e0bd994953d..77f7c1638eb1ce7d3e143bbffd60056e472b1122 100644 (file)
 #define SO_RCVTIMEO_NEW         66
 #define SO_SNDTIMEO_NEW         67
 
+#define SO_DETACH_REUSEPORT_BPF 68
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
index 75b1c950b49fde74187835bdb3b4952b43ba19af..06be30737b69fd53de3ff721bc4a193d148b3448 100644 (file)
@@ -1045,6 +1045,10 @@ set_rcvbuf:
                }
                break;
 
+       case SO_DETACH_REUSEPORT_BPF:
+               ret = reuseport_detach_prog(sk);
+               break;
+
        case SO_DETACH_FILTER:
                ret = sk_detach_filter(sk);
                break;
index dc4aefdf2a084b0ec46cc14415dcfda00a9aaa3d..9408f9264d052298a4eb85e0fb232c89af533e5c 100644 (file)
@@ -332,3 +332,27 @@ int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog)
        return 0;
 }
 EXPORT_SYMBOL(reuseport_attach_prog);
+
+int reuseport_detach_prog(struct sock *sk)
+{
+       struct sock_reuseport *reuse;
+       struct bpf_prog *old_prog;
+
+       if (!rcu_access_pointer(sk->sk_reuseport_cb))
+               return sk->sk_reuseport ? -ENOENT : -EINVAL;
+
+       old_prog = NULL;
+       spin_lock_bh(&reuseport_lock);
+       reuse = rcu_dereference_protected(sk->sk_reuseport_cb,
+                                         lockdep_is_held(&reuseport_lock));
+       rcu_swap_protected(reuse->prog, old_prog,
+                          lockdep_is_held(&reuseport_lock));
+       spin_unlock_bh(&reuseport_lock);
+
+       if (!old_prog)
+               return -ENOENT;
+
+       sk_reuseport_prog_free(old_prog);
+       return 0;
+}
+EXPORT_SYMBOL(reuseport_detach_prog);