bpf, sockmap: Fix missing BPF_F_INGRESS flag when using apply_bytes
authorPengcheng Yang <yangpc@wangsu.com>
Tue, 29 Nov 2022 10:40:39 +0000 (18:40 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 31 Dec 2022 12:14:14 +0000 (13:14 +0100)
[ Upstream commit a351d6087bf7d3d8440d58d3bf244ec64b89394a ]

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: 8934ce2fd081 ("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>
include/linux/skmsg.h
include/net/tcp.h
net/core/skmsg.c
net/ipv4/tcp_bpf.c
net/tls/tls_sw.c

index ba015a7..6e18ca2 100644 (file)
@@ -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)
index 81ef95d..fdac691 100644 (file)
@@ -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)
index f562f7e..dc9b93d 100644 (file)
@@ -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:
index a38db40..2db868c 100644 (file)
@@ -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)
index 794ef3b..c0fea67 100644 (file)
@@ -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);