ktls, sockmap: Fix missing uncharge operation
authorJiayuan Chen <jiayuan.chen@linux.dev>
Fri, 25 Apr 2025 05:59:57 +0000 (13:59 +0800)
committerMartin KaFai Lau <martin.lau@kernel.org>
Sat, 10 May 2025 01:09:59 +0000 (18:09 -0700)
When we specify apply_bytes, we divide the msg into multiple segments,
each with a length of 'send', and every time we send this part of the data
using tcp_bpf_sendmsg_redir(), we use sk_msg_return_zero() to uncharge the
memory of the specified 'send' size.

However, if the first segment of data fails to send, for example, the
peer's buffer is full, we need to release all of the msg. When releasing
the msg, we haven't uncharged the memory of the subsequent segments.

This modification does not make significant logical changes, but only
fills in the missing uncharge places.

This issue has existed all along, until it was exposed after we added the
apply test in test_sockmap:
commit 3448ad23b34e ("selftests/bpf: Add apply_bytes test to test_txmsg_redir_wait_sndmem in test_sockmap")

Fixes: d3b18ad31f93 ("tls: add bpf support to sk_msg handling")
Reported-by: Cong Wang <xiyou.wangcong@gmail.com>
Closes: https://lore.kernel.org/bpf/aAmIi0vlycHtbXeb@pop-os.localdomain/T/#t
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Reviewed-by: Cong Wang <xiyou.wangcong@gmail.com>
Link: https://lore.kernel.org/r/20250425060015.6968-2-jiayuan.chen@linux.dev
net/tls/tls_sw.c

index f3d7d19482da9ab65748c9b7004357fe080cd52b..fc88e34b7f33fefed8aa3c26e1f6eed07cd20853 100644 (file)
@@ -908,6 +908,13 @@ more_data:
                                            &msg_redir, send, flags);
                lock_sock(sk);
                if (err < 0) {
+                       /* Regardless of whether the data represented by
+                        * msg_redir is sent successfully, we have already
+                        * uncharged it via sk_msg_return_zero(). The
+                        * msg->sg.size represents the remaining unprocessed
+                        * data, which needs to be uncharged here.
+                        */
+                       sk_mem_uncharge(sk, msg->sg.size);
                        *copied -= sk_msg_free_nocharge(sk, &msg_redir);
                        msg->sg.size = 0;
                }