bpf, sockmap: Fix missing BPF_F_INGRESS flag when using apply_bytes
[ Upstream commita351d6087b
] When redirecting, we use sk_msg_to_ingress() to get the BPF_F_INGRESS flag from the msg->flags. If apply_bytes is used and it is larger than the current data being processed, sk_psock_msg_verdict() will not be called when sendmsg() is called again. At this time, the msg->flags is 0, and we lost the BPF_F_INGRESS flag. So we need to save the BPF_F_INGRESS flag in sk_psock and use it when redirection. Fixes:8934ce2fd0
("bpf: sockmap redirect ingress support") Signed-off-by: Pengcheng Yang <yangpc@wangsu.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Jakub Sitnicki <jakub@cloudflare.com> Link: https://lore.kernel.org/bpf/1669718441-2654-3-git-send-email-yangpc@wangsu.com Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Родитель
8786bde11a
Коммит
6105ed3598
|
@ -83,6 +83,7 @@ struct sk_psock {
|
|||
u32 apply_bytes;
|
||||
u32 cork_bytes;
|
||||
u32 eval;
|
||||
bool redir_ingress; /* undefined if sk_redir is null */
|
||||
struct sk_msg *cork;
|
||||
struct sk_psock_progs progs;
|
||||
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
||||
|
|
|
@ -2243,8 +2243,8 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore);
|
|||
void tcp_bpf_clone(const struct sock *sk, struct sock *newsk);
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
|
||||
int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, u32 bytes,
|
||||
int flags);
|
||||
int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress,
|
||||
struct sk_msg *msg, u32 bytes, int flags);
|
||||
#endif /* CONFIG_NET_SOCK_MSG */
|
||||
|
||||
#if !defined(CONFIG_BPF_SYSCALL) || !defined(CONFIG_NET_SOCK_MSG)
|
||||
|
|
|
@ -880,13 +880,16 @@ int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock,
|
|||
ret = sk_psock_map_verd(ret, msg->sk_redir);
|
||||
psock->apply_bytes = msg->apply_bytes;
|
||||
if (ret == __SK_REDIRECT) {
|
||||
if (psock->sk_redir)
|
||||
if (psock->sk_redir) {
|
||||
sock_put(psock->sk_redir);
|
||||
psock->sk_redir = msg->sk_redir;
|
||||
if (!psock->sk_redir) {
|
||||
psock->sk_redir = NULL;
|
||||
}
|
||||
if (!msg->sk_redir) {
|
||||
ret = __SK_DROP;
|
||||
goto out;
|
||||
}
|
||||
psock->redir_ingress = sk_msg_to_ingress(msg);
|
||||
psock->sk_redir = msg->sk_redir;
|
||||
sock_hold(psock->sk_redir);
|
||||
}
|
||||
out:
|
||||
|
|
|
@ -131,10 +131,9 @@ static int tcp_bpf_push_locked(struct sock *sk, struct sk_msg *msg,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg,
|
||||
u32 bytes, int flags)
|
||||
int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress,
|
||||
struct sk_msg *msg, u32 bytes, int flags)
|
||||
{
|
||||
bool ingress = sk_msg_to_ingress(msg);
|
||||
struct sk_psock *psock = sk_psock_get(sk);
|
||||
int ret;
|
||||
|
||||
|
@ -277,7 +276,7 @@ msg_bytes_ready:
|
|||
static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock,
|
||||
struct sk_msg *msg, int *copied, int flags)
|
||||
{
|
||||
bool cork = false, enospc = sk_msg_full(msg);
|
||||
bool cork = false, enospc = sk_msg_full(msg), redir_ingress;
|
||||
struct sock *sk_redir;
|
||||
u32 tosend, origsize, sent, delta = 0;
|
||||
u32 eval;
|
||||
|
@ -323,6 +322,7 @@ more_data:
|
|||
sk_msg_apply_bytes(psock, tosend);
|
||||
break;
|
||||
case __SK_REDIRECT:
|
||||
redir_ingress = psock->redir_ingress;
|
||||
sk_redir = psock->sk_redir;
|
||||
sk_msg_apply_bytes(psock, tosend);
|
||||
if (!psock->apply_bytes) {
|
||||
|
@ -339,7 +339,8 @@ more_data:
|
|||
release_sock(sk);
|
||||
|
||||
origsize = msg->sg.size;
|
||||
ret = tcp_bpf_sendmsg_redir(sk_redir, msg, tosend, flags);
|
||||
ret = tcp_bpf_sendmsg_redir(sk_redir, redir_ingress,
|
||||
msg, tosend, flags);
|
||||
sent = origsize - msg->sg.size;
|
||||
|
||||
if (eval == __SK_REDIRECT)
|
||||
|
|
|
@ -801,7 +801,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk,
|
|||
struct sk_psock *psock;
|
||||
struct sock *sk_redir;
|
||||
struct tls_rec *rec;
|
||||
bool enospc, policy;
|
||||
bool enospc, policy, redir_ingress;
|
||||
int err = 0, send;
|
||||
u32 delta = 0;
|
||||
|
||||
|
@ -846,6 +846,7 @@ more_data:
|
|||
}
|
||||
break;
|
||||
case __SK_REDIRECT:
|
||||
redir_ingress = psock->redir_ingress;
|
||||
sk_redir = psock->sk_redir;
|
||||
memcpy(&msg_redir, msg, sizeof(*msg));
|
||||
if (msg->apply_bytes < send)
|
||||
|
@ -855,7 +856,8 @@ more_data:
|
|||
sk_msg_return_zero(sk, msg, send);
|
||||
msg->sg.size -= send;
|
||||
release_sock(sk);
|
||||
err = tcp_bpf_sendmsg_redir(sk_redir, &msg_redir, send, flags);
|
||||
err = tcp_bpf_sendmsg_redir(sk_redir, redir_ingress,
|
||||
&msg_redir, send, flags);
|
||||
lock_sock(sk);
|
||||
if (err < 0) {
|
||||
*copied -= sk_msg_free_nocharge(sk, &msg_redir);
|
||||
|
|
Загрузка…
Ссылка в новой задаче