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

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

index 5310def20e0ca6b47ed5700e247251faa8adcad4..5d134a75cad0ddfe30ef91f59bb3499f825fcc26 100644 (file)
@@ -1545,7 +1545,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
 
        if (needs_rtnl)
                rtnl_lock();
-       lock_sock(sk);
+       sockopt_lock_sock(sk);
 
        switch (optname) {
        case IP_OPTIONS:
@@ -1561,7 +1561,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
                        memcpy(optbuf, &inet_opt->opt,
                               sizeof(struct ip_options) +
                               inet_opt->opt.optlen);
-               release_sock(sk);
+               sockopt_release_sock(sk);
 
                if (opt->optlen == 0) {
                        len = 0;
@@ -1637,7 +1637,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
                        dst_release(dst);
                }
                if (!val) {
-                       release_sock(sk);
+                       sockopt_release_sock(sk);
                        return -ENOTCONN;
                }
                break;
@@ -1662,7 +1662,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
                struct in_addr addr;
                len = min_t(unsigned int, len, sizeof(struct in_addr));
                addr.s_addr = inet->mc_addr;
-               release_sock(sk);
+               sockopt_release_sock(sk);
 
                if (copy_to_sockptr(optlen, &len, sizeof(int)))
                        return -EFAULT;
@@ -1699,7 +1699,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
        {
                struct msghdr msg;
 
-               release_sock(sk);
+               sockopt_release_sock(sk);
 
                if (sk->sk_type != SOCK_STREAM)
                        return -ENOPROTOOPT;
@@ -1743,10 +1743,10 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
                val = inet->min_ttl;
                break;
        default:
-               release_sock(sk);
+               sockopt_release_sock(sk);
                return -ENOPROTOOPT;
        }
-       release_sock(sk);
+       sockopt_release_sock(sk);
 
        if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) {
                unsigned char ucval = (unsigned char)val;
@@ -1765,7 +1765,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
        return 0;
 
 out:
-       release_sock(sk);
+       sockopt_release_sock(sk);
        if (needs_rtnl)
                rtnl_unlock();
        return err;