soreuseport: Prep for fast reuseport TCP socket selection
authorCraig Gallek <kraig@google.com>
Wed, 10 Feb 2016 16:50:39 +0000 (11:50 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 11 Feb 2016 08:54:15 +0000 (03:54 -0500)
Both of the lines in this patch probably should have been included
in the initial implementation of this code for generic socket
support, but weren't technically necessary since only UDP sockets
were supported.

First, the sk_reuseport_cb points to a structure which assumes
each socket in the group has this pointer assigned at the same
time it's added to the array in the structure.  The sk_clone_lock
function breaks this assumption.  Since a child socket shouldn't
implicitly be in a reuseport group, the simple fix is to clear
the field in the clone.

Second, the SO_ATTACH_REUSEPORT_xBPF socket options require that
SO_REUSEPORT also be set first.  For UDP sockets, this is easily
enforced at bind-time since that process both puts the socket in
the appropriate receive hlist and updates the reuseport structures.
Since these operations can happen at two different times for TCP
sockets (bind and listen) it must be explicitly checked to enforce
the use of SO_REUSEPORT with SO_ATTACH_REUSEPORT_xBPF in the
setsockopt call.

Signed-off-by: Craig Gallek <kraig@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/filter.c
net/core/sock.c

index 94d26201080d6671080f63865994bb41d7d3d8bc..2a6e9562f1ab0c57b78e025c59a118524137fb1e 100644 (file)
@@ -1181,7 +1181,7 @@ static int __reuseport_attach_prog(struct bpf_prog *prog, struct sock *sk)
        if (bpf_prog_size(prog->len) > sysctl_optmem_max)
                return -ENOMEM;
 
-       if (sk_unhashed(sk)) {
+       if (sk_unhashed(sk) && sk->sk_reuseport) {
                err = reuseport_alloc(sk);
                if (err)
                        return err;
index 6c1c8bc934127c48bb5e0a95961e61c5b79da5b4..46dc8ad7d0501d9fec698930d85798371d7932ea 100644 (file)
@@ -1531,6 +1531,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
                        newsk = NULL;
                        goto out;
                }
+               RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL);
 
                newsk->sk_err      = 0;
                newsk->sk_priority = 0;