Commit 9201f60a authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'a-few-corrections-for-sock_support_zc'

Pavel Begunkov says:

====================
a few corrections for SOCK_SUPPORT_ZC

There are several places/cases that got overlooked in regards to
SOCK_SUPPORT_ZC. We're lacking the flag for IPv6 UDP sockets and
accepted TCP sockets. We also should clear the flag when someone
tries to hijack a socket by replacing the ->sk_prot callbacks.
====================

Link: https://lore.kernel.org/r/cover.1666825799.git.asml.silence@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 1208b93d 71b7786e
...@@ -1889,6 +1889,13 @@ void sock_kfree_s(struct sock *sk, void *mem, int size); ...@@ -1889,6 +1889,13 @@ void sock_kfree_s(struct sock *sk, void *mem, int size);
void sock_kzfree_s(struct sock *sk, void *mem, int size); void sock_kzfree_s(struct sock *sk, void *mem, int size);
void sk_send_sigurg(struct sock *sk); void sk_send_sigurg(struct sock *sk);
static inline void sock_replace_proto(struct sock *sk, struct proto *proto)
{
if (sk->sk_socket)
clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
WRITE_ONCE(sk->sk_prot, proto);
}
struct sockcm_cookie { struct sockcm_cookie {
u64 transmit_time; u64 transmit_time;
u32 mark; u32 mark;
......
...@@ -754,6 +754,8 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags, ...@@ -754,6 +754,8 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags,
(TCPF_ESTABLISHED | TCPF_SYN_RECV | (TCPF_ESTABLISHED | TCPF_SYN_RECV |
TCPF_CLOSE_WAIT | TCPF_CLOSE))); TCPF_CLOSE_WAIT | TCPF_CLOSE)));
if (test_bit(SOCK_SUPPORT_ZC, &sock->flags))
set_bit(SOCK_SUPPORT_ZC, &newsock->flags);
sock_graft(sk2, newsock); sock_graft(sk2, newsock);
newsock->state = SS_CONNECTED; newsock->state = SS_CONNECTED;
......
...@@ -607,7 +607,7 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) ...@@ -607,7 +607,7 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
} else { } else {
sk->sk_write_space = psock->saved_write_space; sk->sk_write_space = psock->saved_write_space;
/* Pairs with lockless read in sk_clone_lock() */ /* Pairs with lockless read in sk_clone_lock() */
WRITE_ONCE(sk->sk_prot, psock->sk_proto); sock_replace_proto(sk, psock->sk_proto);
} }
return 0; return 0;
} }
...@@ -620,7 +620,7 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) ...@@ -620,7 +620,7 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
} }
/* Pairs with lockless read in sk_clone_lock() */ /* Pairs with lockless read in sk_clone_lock() */
WRITE_ONCE(sk->sk_prot, &tcp_bpf_prots[family][config]); sock_replace_proto(sk, &tcp_bpf_prots[family][config]);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(tcp_bpf_update_proto); EXPORT_SYMBOL_GPL(tcp_bpf_update_proto);
......
...@@ -136,6 +136,9 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops) ...@@ -136,6 +136,9 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
if (icsk->icsk_ulp_ops) if (icsk->icsk_ulp_ops)
goto out_err; goto out_err;
if (sk->sk_socket)
clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
err = ulp_ops->init(sk); err = ulp_ops->init(sk);
if (err) if (err)
goto out_err; goto out_err;
......
...@@ -141,14 +141,14 @@ int udp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) ...@@ -141,14 +141,14 @@ int udp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
if (restore) { if (restore) {
sk->sk_write_space = psock->saved_write_space; sk->sk_write_space = psock->saved_write_space;
WRITE_ONCE(sk->sk_prot, psock->sk_proto); sock_replace_proto(sk, psock->sk_proto);
return 0; return 0;
} }
if (sk->sk_family == AF_INET6) if (sk->sk_family == AF_INET6)
udp_bpf_check_v6_needs_rebuild(psock->sk_proto); udp_bpf_check_v6_needs_rebuild(psock->sk_proto);
WRITE_ONCE(sk->sk_prot, &udp_bpf_prots[family]); sock_replace_proto(sk, &udp_bpf_prots[family]);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(udp_bpf_update_proto); EXPORT_SYMBOL_GPL(udp_bpf_update_proto);
...@@ -66,6 +66,7 @@ int udpv6_init_sock(struct sock *sk) ...@@ -66,6 +66,7 @@ int udpv6_init_sock(struct sock *sk)
{ {
skb_queue_head_init(&udp_sk(sk)->reader_queue); skb_queue_head_init(&udp_sk(sk)->reader_queue);
sk->sk_destruct = udpv6_destruct_sock; sk->sk_destruct = udpv6_destruct_sock;
set_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
return 0; return 0;
} }
......
...@@ -145,12 +145,12 @@ int unix_dgram_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool re ...@@ -145,12 +145,12 @@ int unix_dgram_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool re
if (restore) { if (restore) {
sk->sk_write_space = psock->saved_write_space; sk->sk_write_space = psock->saved_write_space;
WRITE_ONCE(sk->sk_prot, psock->sk_proto); sock_replace_proto(sk, psock->sk_proto);
return 0; return 0;
} }
unix_dgram_bpf_check_needs_rebuild(psock->sk_proto); unix_dgram_bpf_check_needs_rebuild(psock->sk_proto);
WRITE_ONCE(sk->sk_prot, &unix_dgram_bpf_prot); sock_replace_proto(sk, &unix_dgram_bpf_prot);
return 0; return 0;
} }
...@@ -158,12 +158,12 @@ int unix_stream_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool r ...@@ -158,12 +158,12 @@ int unix_stream_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool r
{ {
if (restore) { if (restore) {
sk->sk_write_space = psock->saved_write_space; sk->sk_write_space = psock->saved_write_space;
WRITE_ONCE(sk->sk_prot, psock->sk_proto); sock_replace_proto(sk, psock->sk_proto);
return 0; return 0;
} }
unix_stream_bpf_check_needs_rebuild(psock->sk_proto); unix_stream_bpf_check_needs_rebuild(psock->sk_proto);
WRITE_ONCE(sk->sk_prot, &unix_stream_bpf_prot); sock_replace_proto(sk, &unix_stream_bpf_prot);
return 0; return 0;
} }
......
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