Commit 1985320c authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by Alexei Starovoitov

bpf: net: Avoid do_ip_getsockopt() taking sk lock when called from bpf

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: default avatarMartin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20220902002834.2891514-1-kafai@fb.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 728f064c
...@@ -1545,7 +1545,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, ...@@ -1545,7 +1545,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
if (needs_rtnl) if (needs_rtnl)
rtnl_lock(); rtnl_lock();
lock_sock(sk); sockopt_lock_sock(sk);
switch (optname) { switch (optname) {
case IP_OPTIONS: case IP_OPTIONS:
...@@ -1561,7 +1561,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, ...@@ -1561,7 +1561,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
memcpy(optbuf, &inet_opt->opt, memcpy(optbuf, &inet_opt->opt,
sizeof(struct ip_options) + sizeof(struct ip_options) +
inet_opt->opt.optlen); inet_opt->opt.optlen);
release_sock(sk); sockopt_release_sock(sk);
if (opt->optlen == 0) { if (opt->optlen == 0) {
len = 0; len = 0;
...@@ -1637,7 +1637,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, ...@@ -1637,7 +1637,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
dst_release(dst); dst_release(dst);
} }
if (!val) { if (!val) {
release_sock(sk); sockopt_release_sock(sk);
return -ENOTCONN; return -ENOTCONN;
} }
break; break;
...@@ -1662,7 +1662,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, ...@@ -1662,7 +1662,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
struct in_addr addr; struct in_addr addr;
len = min_t(unsigned int, len, sizeof(struct in_addr)); len = min_t(unsigned int, len, sizeof(struct in_addr));
addr.s_addr = inet->mc_addr; addr.s_addr = inet->mc_addr;
release_sock(sk); sockopt_release_sock(sk);
if (copy_to_sockptr(optlen, &len, sizeof(int))) if (copy_to_sockptr(optlen, &len, sizeof(int)))
return -EFAULT; return -EFAULT;
...@@ -1699,7 +1699,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, ...@@ -1699,7 +1699,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
{ {
struct msghdr msg; struct msghdr msg;
release_sock(sk); sockopt_release_sock(sk);
if (sk->sk_type != SOCK_STREAM) if (sk->sk_type != SOCK_STREAM)
return -ENOPROTOOPT; return -ENOPROTOOPT;
...@@ -1743,10 +1743,10 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, ...@@ -1743,10 +1743,10 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
val = inet->min_ttl; val = inet->min_ttl;
break; break;
default: default:
release_sock(sk); sockopt_release_sock(sk);
return -ENOPROTOOPT; return -ENOPROTOOPT;
} }
release_sock(sk); sockopt_release_sock(sk);
if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) { if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) {
unsigned char ucval = (unsigned char)val; unsigned char ucval = (unsigned char)val;
...@@ -1765,7 +1765,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, ...@@ -1765,7 +1765,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
return 0; return 0;
out: out:
release_sock(sk); sockopt_release_sock(sk);
if (needs_rtnl) if (needs_rtnl)
rtnl_unlock(); rtnl_unlock();
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment