Skip to content

Commit 79ffe60

Browse files
Jakub Kicinskidavem330
authored andcommitted
net/tls: add a TX lock
TLS TX needs to release and re-acquire the socket lock if send buffer fills up. TLS SW TX path currently depends on only allowing one thread to enter the function by the abuse of sk_write_pending. If another writer is already waiting for memory no new ones are allowed in. This has two problems: - writers don't wake other threads up when they leave the kernel; meaning that this scheme works for single extra thread (second application thread or delayed work) because memory becoming available will send a wake up request, but as Mallesham and Pooja report with larger number of threads it leads to threads being put to sleep indefinitely; - the delayed work does not get _scheduled_ but it may _run_ when other writers are present leading to crashes as writers don't expect state to change under their feet (same records get pushed and freed multiple times); it's hard to reliably bail from the work, however, because the mere presence of a writer does not guarantee that the writer will push pending records before exiting. Ensuring wakeups always happen will make the code basically open code a mutex. Just use a mutex. The TLS HW TX path does not have any locking (not even the sk_write_pending hack), yet it uses a per-socket sg_tx_data array to push records. Fixes: a42055e ("net/tls: Add support for async encryption of records for performance") Reported-by: Mallesham Jatharakonda <mallesh537@gmail.com> Reported-by: Pooja Trivedi <poojatrivedi@gmail.com> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 02b1fa0 commit 79ffe60

File tree

4 files changed

+20
-14
lines changed

4 files changed

+20
-14
lines changed

include/net/tls.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <linux/socket.h>
4141
#include <linux/tcp.h>
4242
#include <linux/skmsg.h>
43+
#include <linux/mutex.h>
4344
#include <linux/netdevice.h>
4445
#include <linux/rcupdate.h>
4546

@@ -269,6 +270,10 @@ struct tls_context {
269270

270271
bool in_tcp_sendpages;
271272
bool pending_open_record_frags;
273+
274+
struct mutex tx_lock; /* protects partially_sent_* fields and
275+
* per-type TX fields
276+
*/
272277
unsigned long flags;
273278

274279
/* cache cold stuff */

net/tls/tls_device.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,10 @@ static int tls_push_data(struct sock *sk,
523523
int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
524524
{
525525
unsigned char record_type = TLS_RECORD_TYPE_DATA;
526+
struct tls_context *tls_ctx = tls_get_ctx(sk);
526527
int rc;
527528

529+
mutex_lock(&tls_ctx->tx_lock);
528530
lock_sock(sk);
529531

530532
if (unlikely(msg->msg_controllen)) {
@@ -538,12 +540,14 @@ int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
538540

539541
out:
540542
release_sock(sk);
543+
mutex_unlock(&tls_ctx->tx_lock);
541544
return rc;
542545
}
543546

544547
int tls_device_sendpage(struct sock *sk, struct page *page,
545548
int offset, size_t size, int flags)
546549
{
550+
struct tls_context *tls_ctx = tls_get_ctx(sk);
547551
struct iov_iter msg_iter;
548552
char *kaddr = kmap(page);
549553
struct kvec iov;
@@ -552,6 +556,7 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
552556
if (flags & MSG_SENDPAGE_NOTLAST)
553557
flags |= MSG_MORE;
554558

559+
mutex_lock(&tls_ctx->tx_lock);
555560
lock_sock(sk);
556561

557562
if (flags & MSG_OOB) {
@@ -568,6 +573,7 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
568573

569574
out:
570575
release_sock(sk);
576+
mutex_unlock(&tls_ctx->tx_lock);
571577
return rc;
572578
}
573579

net/tls/tls_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ void tls_ctx_free(struct sock *sk, struct tls_context *ctx)
267267

268268
memzero_explicit(&ctx->crypto_send, sizeof(ctx->crypto_send));
269269
memzero_explicit(&ctx->crypto_recv, sizeof(ctx->crypto_recv));
270+
mutex_destroy(&ctx->tx_lock);
270271

271272
if (sk)
272273
kfree_rcu(ctx, rcu);
@@ -612,6 +613,7 @@ static struct tls_context *create_ctx(struct sock *sk)
612613
if (!ctx)
613614
return NULL;
614615

616+
mutex_init(&ctx->tx_lock);
615617
rcu_assign_pointer(icsk->icsk_ulp_data, ctx);
616618
ctx->sk_proto = sk->sk_prot;
617619
return ctx;

net/tls/tls_sw.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -897,15 +897,9 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
897897
if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL))
898898
return -ENOTSUPP;
899899

900+
mutex_lock(&tls_ctx->tx_lock);
900901
lock_sock(sk);
901902

902-
/* Wait till there is any pending write on socket */
903-
if (unlikely(sk->sk_write_pending)) {
904-
ret = wait_on_pending_writer(sk, &timeo);
905-
if (unlikely(ret))
906-
goto send_end;
907-
}
908-
909903
if (unlikely(msg->msg_controllen)) {
910904
ret = tls_proccess_cmsg(sk, msg, &record_type);
911905
if (ret) {
@@ -1091,6 +1085,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
10911085
ret = sk_stream_error(sk, msg->msg_flags, ret);
10921086

10931087
release_sock(sk);
1088+
mutex_unlock(&tls_ctx->tx_lock);
10941089
return copied ? copied : ret;
10951090
}
10961091

@@ -1114,13 +1109,6 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page,
11141109
eor = !(flags & (MSG_MORE | MSG_SENDPAGE_NOTLAST));
11151110
sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
11161111

1117-
/* Wait till there is any pending write on socket */
1118-
if (unlikely(sk->sk_write_pending)) {
1119-
ret = wait_on_pending_writer(sk, &timeo);
1120-
if (unlikely(ret))
1121-
goto sendpage_end;
1122-
}
1123-
11241112
/* Call the sk_stream functions to manage the sndbuf mem. */
11251113
while (size > 0) {
11261114
size_t copy, required_size;
@@ -1219,15 +1207,18 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page,
12191207
int tls_sw_sendpage(struct sock *sk, struct page *page,
12201208
int offset, size_t size, int flags)
12211209
{
1210+
struct tls_context *tls_ctx = tls_get_ctx(sk);
12221211
int ret;
12231212

12241213
if (flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL |
12251214
MSG_SENDPAGE_NOTLAST | MSG_SENDPAGE_NOPOLICY))
12261215
return -ENOTSUPP;
12271216

1217+
mutex_lock(&tls_ctx->tx_lock);
12281218
lock_sock(sk);
12291219
ret = tls_sw_do_sendpage(sk, page, offset, size, flags);
12301220
release_sock(sk);
1221+
mutex_unlock(&tls_ctx->tx_lock);
12311222
return ret;
12321223
}
12331224

@@ -2170,9 +2161,11 @@ static void tx_work_handler(struct work_struct *work)
21702161

21712162
if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
21722163
return;
2164+
mutex_lock(&tls_ctx->tx_lock);
21732165
lock_sock(sk);
21742166
tls_tx_records(sk, -1);
21752167
release_sock(sk);
2168+
mutex_unlock(&tls_ctx->tx_lock);
21762169
}
21772170

21782171
void tls_sw_write_space(struct sock *sk, struct tls_context *ctx)

0 commit comments

Comments
 (0)