Commit d51bbff2 authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by Alexei Starovoitov
Browse files

bpf: net: Avoid do_tcp_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_tcp_getsockopt()
to use sockopt_{lock,release}_sock() such that a latter patch can
make bpf_getsockopt(SOL_TCP) to reuse do_tcp_getsockopt().

Signed-off-by: default avatarMartin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20220902002821.2889765-1-kafai@fb.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 34704ef0
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -4265,30 +4265,30 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
		if (copy_from_sockptr(&len, optlen, sizeof(int)))
			return -EFAULT;

		lock_sock(sk);
		sockopt_lock_sock(sk);
		if (tp->saved_syn) {
			if (len < tcp_saved_syn_len(tp->saved_syn)) {
				len = tcp_saved_syn_len(tp->saved_syn);
				if (copy_to_sockptr(optlen, &len, sizeof(int))) {
					release_sock(sk);
					sockopt_release_sock(sk);
					return -EFAULT;
				}
				release_sock(sk);
				sockopt_release_sock(sk);
				return -EINVAL;
			}
			len = tcp_saved_syn_len(tp->saved_syn);
			if (copy_to_sockptr(optlen, &len, sizeof(int))) {
				release_sock(sk);
				sockopt_release_sock(sk);
				return -EFAULT;
			}
			if (copy_to_sockptr(optval, tp->saved_syn->data, len)) {
				release_sock(sk);
				sockopt_release_sock(sk);
				return -EFAULT;
			}
			tcp_saved_syn_free(tp);
			release_sock(sk);
			sockopt_release_sock(sk);
		} else {
			release_sock(sk);
			sockopt_release_sock(sk);
			len = 0;
			if (copy_to_sockptr(optlen, &len, sizeof(int)))
				return -EFAULT;
@@ -4321,11 +4321,11 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
			return -EINVAL;
		if (zc.msg_flags &  ~(TCP_VALID_ZC_MSG_FLAGS))
			return -EINVAL;
		lock_sock(sk);
		sockopt_lock_sock(sk);
		err = tcp_zerocopy_receive(sk, &zc, &tss);
		err = BPF_CGROUP_RUN_PROG_GETSOCKOPT_KERN(sk, level, optname,
							  &zc, &len, err);
		release_sock(sk);
		sockopt_release_sock(sk);
		if (len >= offsetofend(struct tcp_zerocopy_receive, msg_flags))
			goto zerocopy_rcv_cmsg;
		switch (len) {