Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'bpf-fix-ktls-panic-with-sockmap-and-add-tests'

Jiayuan Chen says:

====================
bpf: fix ktls panic with sockmap and add tests

We can reproduce the issue using the existing test program:
'./test_sockmap --ktls'
Or use the selftest I provided, which will cause a panic:

------------[ cut here ]------------
kernel BUG at lib/iov_iter.c:629!

PKRU: 55555554
Call Trace:
<TASK>
? die+0x36/0x90
? do_trap+0xdd/0x100
? iov_iter_revert+0x178/0x180
? iov_iter_revert+0x178/0x180
? do_error_trap+0x7d/0x110
? iov_iter_revert+0x178/0x180
? exc_invalid_op+0x50/0x70
? iov_iter_revert+0x178/0x180
? asm_exc_invalid_op+0x1a/0x20
? iov_iter_revert+0x178/0x180
? iov_iter_revert+0x5c/0x180
tls_sw_sendmsg_locked.isra.0+0x794/0x840
tls_sw_sendmsg+0x52/0x80
? inet_sendmsg+0x1f/0x70
__sys_sendto+0x1cd/0x200
? find_held_lock+0x2b/0x80
? syscall_trace_enter+0x140/0x270
? __lock_release.isra.0+0x5e/0x170
? find_held_lock+0x2b/0x80
? syscall_trace_enter+0x140/0x270
? lockdep_hardirqs_on_prepare+0xda/0x190
? ktime_get_coarse_real_ts64+0xc2/0xd0
__x64_sys_sendto+0x24/0x30
do_syscall_64+0x90/0x170

1. It looks like the issue started occurring after bpf being introduced to
ktls and later the addition of assertions to iov_iter has caused a panic.
If my fix tag is incorrect, please assist me in correcting the fix tag.

2. I make minimal changes for now, it's enough to make ktls work
correctly.
---
v1->v2: Added more content to the commit message
https://lore.kernel.org/all/20250123171552.57345-1-mrpre@163.com/#r
---
====================

Link: https://patch.msgid.link/20250219052015.274405-1-jiayuan.chen@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+205 -3
+6 -2
net/tls/tls_sw.c
··· 1120 1120 num_async++; 1121 1121 else if (ret == -ENOMEM) 1122 1122 goto wait_for_memory; 1123 - else if (ctx->open_rec && ret == -ENOSPC) 1123 + else if (ctx->open_rec && ret == -ENOSPC) { 1124 + if (msg_pl->cork_bytes) { 1125 + ret = 0; 1126 + goto send_end; 1127 + } 1124 1128 goto rollback_iter; 1125 - else if (ret != -EAGAIN) 1129 + } else if (ret != -EAGAIN) 1126 1130 goto send_end; 1127 1131 } 1128 1132 continue;
+173 -1
tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c
··· 3 3 /* 4 4 * Tests for sockmap/sockhash holding kTLS sockets. 5 5 */ 6 - 6 + #include <error.h> 7 7 #include <netinet/tcp.h> 8 + #include <linux/tls.h> 8 9 #include "test_progs.h" 10 + #include "sockmap_helpers.h" 11 + #include "test_skmsg_load_helpers.skel.h" 12 + #include "test_sockmap_ktls.skel.h" 9 13 10 14 #define MAX_TEST_NAME 80 11 15 #define TCP_ULP 31 16 + 17 + static int init_ktls_pairs(int c, int p) 18 + { 19 + int err; 20 + struct tls12_crypto_info_aes_gcm_128 crypto_rx; 21 + struct tls12_crypto_info_aes_gcm_128 crypto_tx; 22 + 23 + err = setsockopt(c, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls")); 24 + if (!ASSERT_OK(err, "setsockopt(TCP_ULP)")) 25 + goto out; 26 + 27 + err = setsockopt(p, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls")); 28 + if (!ASSERT_OK(err, "setsockopt(TCP_ULP)")) 29 + goto out; 30 + 31 + memset(&crypto_rx, 0, sizeof(crypto_rx)); 32 + memset(&crypto_tx, 0, sizeof(crypto_tx)); 33 + crypto_rx.info.version = TLS_1_2_VERSION; 34 + crypto_tx.info.version = TLS_1_2_VERSION; 35 + crypto_rx.info.cipher_type = TLS_CIPHER_AES_GCM_128; 36 + crypto_tx.info.cipher_type = TLS_CIPHER_AES_GCM_128; 37 + 38 + err = setsockopt(c, SOL_TLS, TLS_TX, &crypto_tx, sizeof(crypto_tx)); 39 + if (!ASSERT_OK(err, "setsockopt(TLS_TX)")) 40 + goto out; 41 + 42 + err = setsockopt(p, SOL_TLS, TLS_RX, &crypto_rx, sizeof(crypto_rx)); 43 + if (!ASSERT_OK(err, "setsockopt(TLS_RX)")) 44 + goto out; 45 + return 0; 46 + out: 47 + return -1; 48 + } 49 + 50 + static int create_ktls_pairs(int family, int sotype, int *c, int *p) 51 + { 52 + int err; 53 + 54 + err = create_pair(family, sotype, c, p); 55 + if (!ASSERT_OK(err, "create_pair()")) 56 + return -1; 57 + 58 + err = init_ktls_pairs(*c, *p); 59 + if (!ASSERT_OK(err, "init_ktls_pairs(c, p)")) 60 + return -1; 61 + return 0; 62 + } 12 63 13 64 static int tcp_server(int family) 14 65 { ··· 197 146 return test_name; 198 147 } 199 148 149 + static void test_sockmap_ktls_offload(int family, int sotype) 150 + { 151 + int err; 152 + int c = 0, p = 0, sent, recvd; 153 + char msg[12] = "hello world\0"; 154 + char rcv[13]; 155 + 156 + err = create_ktls_pairs(family, sotype, &c, &p); 157 + if (!ASSERT_OK(err, "create_ktls_pairs()")) 158 + goto out; 159 + 160 + sent = send(c, msg, sizeof(msg), 0); 161 + if (!ASSERT_OK(err, "send(msg)")) 162 + goto out; 163 + 164 + recvd = recv(p, rcv, sizeof(rcv), 0); 165 + if (!ASSERT_OK(err, "recv(msg)") || 166 + !ASSERT_EQ(recvd, sent, "length mismatch")) 167 + goto out; 168 + 169 + ASSERT_OK(memcmp(msg, rcv, sizeof(msg)), "data mismatch"); 170 + 171 + out: 172 + if (c) 173 + close(c); 174 + if (p) 175 + close(p); 176 + } 177 + 178 + static void test_sockmap_ktls_tx_cork(int family, int sotype, bool push) 179 + { 180 + int err, off; 181 + int i, j; 182 + int start_push = 0, push_len = 0; 183 + int c = 0, p = 0, one = 1, sent, recvd; 184 + int prog_fd, map_fd; 185 + char msg[12] = "hello world\0"; 186 + char rcv[20] = {0}; 187 + struct test_sockmap_ktls *skel; 188 + 189 + skel = test_sockmap_ktls__open_and_load(); 190 + if (!ASSERT_TRUE(skel, "open ktls skel")) 191 + return; 192 + 193 + err = create_pair(family, sotype, &c, &p); 194 + if (!ASSERT_OK(err, "create_pair()")) 195 + goto out; 196 + 197 + prog_fd = bpf_program__fd(skel->progs.prog_sk_policy); 198 + map_fd = bpf_map__fd(skel->maps.sock_map); 199 + 200 + err = bpf_prog_attach(prog_fd, map_fd, BPF_SK_MSG_VERDICT, 0); 201 + if (!ASSERT_OK(err, "bpf_prog_attach sk msg")) 202 + goto out; 203 + 204 + err = bpf_map_update_elem(map_fd, &one, &c, BPF_NOEXIST); 205 + if (!ASSERT_OK(err, "bpf_map_update_elem(c)")) 206 + goto out; 207 + 208 + err = init_ktls_pairs(c, p); 209 + if (!ASSERT_OK(err, "init_ktls_pairs(c, p)")) 210 + goto out; 211 + 212 + skel->bss->cork_byte = sizeof(msg); 213 + if (push) { 214 + start_push = 1; 215 + push_len = 2; 216 + } 217 + skel->bss->push_start = start_push; 218 + skel->bss->push_end = push_len; 219 + 220 + off = sizeof(msg) / 2; 221 + sent = send(c, msg, off, 0); 222 + if (!ASSERT_EQ(sent, off, "send(msg)")) 223 + goto out; 224 + 225 + recvd = recv_timeout(p, rcv, sizeof(rcv), MSG_DONTWAIT, 1); 226 + if (!ASSERT_EQ(-1, recvd, "expected no data")) 227 + goto out; 228 + 229 + /* send remaining msg */ 230 + sent = send(c, msg + off, sizeof(msg) - off, 0); 231 + if (!ASSERT_EQ(sent, sizeof(msg) - off, "send remaining data")) 232 + goto out; 233 + 234 + recvd = recv_timeout(p, rcv, sizeof(rcv), MSG_DONTWAIT, 1); 235 + if (!ASSERT_OK(err, "recv(msg)") || 236 + !ASSERT_EQ(recvd, sizeof(msg) + push_len, "check length mismatch")) 237 + goto out; 238 + 239 + for (i = 0, j = 0; i < recvd;) { 240 + /* skip checking the data that has been pushed in */ 241 + if (i >= start_push && i <= start_push + push_len - 1) { 242 + i++; 243 + continue; 244 + } 245 + if (!ASSERT_EQ(rcv[i], msg[j], "data mismatch")) 246 + goto out; 247 + i++; 248 + j++; 249 + } 250 + out: 251 + if (c) 252 + close(c); 253 + if (p) 254 + close(p); 255 + test_sockmap_ktls__destroy(skel); 256 + } 257 + 200 258 static void run_tests(int family, enum bpf_map_type map_type) 201 259 { 202 260 int map; ··· 322 162 close(map); 323 163 } 324 164 165 + static void run_ktls_test(int family, int sotype) 166 + { 167 + if (test__start_subtest("tls simple offload")) 168 + test_sockmap_ktls_offload(family, sotype); 169 + if (test__start_subtest("tls tx cork")) 170 + test_sockmap_ktls_tx_cork(family, sotype, false); 171 + if (test__start_subtest("tls tx cork with push")) 172 + test_sockmap_ktls_tx_cork(family, sotype, true); 173 + } 174 + 325 175 void test_sockmap_ktls(void) 326 176 { 327 177 run_tests(AF_INET, BPF_MAP_TYPE_SOCKMAP); 328 178 run_tests(AF_INET, BPF_MAP_TYPE_SOCKHASH); 329 179 run_tests(AF_INET6, BPF_MAP_TYPE_SOCKMAP); 330 180 run_tests(AF_INET6, BPF_MAP_TYPE_SOCKHASH); 181 + run_ktls_test(AF_INET, SOCK_STREAM); 182 + run_ktls_test(AF_INET6, SOCK_STREAM); 331 183 }
+26
tools/testing/selftests/bpf/progs/test_sockmap_ktls.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/bpf.h> 3 + #include <bpf/bpf_helpers.h> 4 + #include <bpf/bpf_endian.h> 5 + 6 + int cork_byte; 7 + int push_start; 8 + int push_end; 9 + 10 + struct { 11 + __uint(type, BPF_MAP_TYPE_SOCKMAP); 12 + __uint(max_entries, 20); 13 + __type(key, int); 14 + __type(value, int); 15 + } sock_map SEC(".maps"); 16 + 17 + SEC("sk_msg") 18 + int prog_sk_policy(struct sk_msg_md *msg) 19 + { 20 + if (cork_byte > 0) 21 + bpf_msg_cork_bytes(msg, cork_byte); 22 + if (push_start > 0 && push_end > 0) 23 + bpf_msg_push_data(msg, push_start, push_end, 0); 24 + 25 + return SK_PASS; 26 + }