bpf: net: Avoid do_ipv6_getsockopt() taking sk lock when called from bpf
authorMartin KaFai Lau <martin.lau@kernel.org>
Fri, 2 Sep 2022 00:28:59 +0000 (17:28 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 3 Sep 2022 03:34:31 +0000 (20:34 -0700)
Similar to the earlier patch that changes sk_getsockopt() to
use sockopt_{lock,release}_sock() such that it can avoid taking the
lock when called from bpf.  This patch also changes do_ipv6_getsockopt()
to use sockopt_{lock,release}_sock() such that bpf_getsockopt(SOL_IPV6)
can reuse do_ipv6_getsockopt().

Although bpf_getsockopt(SOL_IPV6) currently does not support optname
that requires lock_sock(), using sockopt_{lock,release}_sock()
consistently across *_getsockopt() will make future optname addition
harder to miss the sockopt_{lock,release}_sock() usage. eg. when
adding new optname that requires a lock and the new optname is
needed in bpf_getsockopt() also.

Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20220902002859.2893064-1-kafai@fb.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
net/ipv6/ipv6_sockglue.c

index 4d9fade..d9887e3 100644 (file)
@@ -1078,7 +1078,7 @@ static int ipv6_get_msfilter(struct sock *sk, sockptr_t optval,
        if (gsf.gf_group.ss_family != AF_INET6)
                return -EADDRNOTAVAIL;
        num = gsf.gf_numsrc;
-       lock_sock(sk);
+       sockopt_lock_sock(sk);
        err = ip6_mc_msfget(sk, &gsf, optval, size0);
        if (!err) {
                if (num > gsf.gf_numsrc)
@@ -1088,7 +1088,7 @@ static int ipv6_get_msfilter(struct sock *sk, sockptr_t optval,
                    copy_to_sockptr(optval, &gsf, size0))
                        err = -EFAULT;
        }
-       release_sock(sk);
+       sockopt_release_sock(sk);
        return err;
 }
 
@@ -1114,9 +1114,9 @@ static int compat_ipv6_get_msfilter(struct sock *sk, sockptr_t optval,
        if (gf.gf_group.ss_family != AF_INET6)
                return -EADDRNOTAVAIL;
 
-       lock_sock(sk);
+       sockopt_lock_sock(sk);
        err = ip6_mc_msfget(sk, &gf, optval, size0);
-       release_sock(sk);
+       sockopt_release_sock(sk);
        if (err)
                return err;
        if (num > gf.gf_numsrc)
@@ -1175,11 +1175,11 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                msg.msg_controllen = len;
                msg.msg_flags = 0;
 
-               lock_sock(sk);
+               sockopt_lock_sock(sk);
                skb = np->pktoptions;
                if (skb)
                        ip6_datagram_recv_ctl(sk, &msg, skb);
-               release_sock(sk);
+               sockopt_release_sock(sk);
                if (!skb) {
                        if (np->rxopt.bits.rxinfo) {
                                struct in6_pktinfo src_info;
@@ -1268,11 +1268,11 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
        {
                struct ipv6_txoptions *opt;
 
-               lock_sock(sk);
+               sockopt_lock_sock(sk);
                opt = rcu_dereference_protected(np->opt,
                                                lockdep_sock_is_held(sk));
                len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len);
-               release_sock(sk);
+               sockopt_release_sock(sk);
                /* check if ipv6_getsockopt_sticky() returns err code */
                if (len < 0)
                        return len;