summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Kicinski <jakub.kicinski@netronome.com>2019-11-05 17:24:35 -0500
committerDavid S. Miller <davem@davemloft.net>2019-11-06 20:33:32 -0500
commit79ffe6087e9145d2377385cac48d0d6a6b4225a5 (patch)
tree7ad119676734db269b7ae127d3bf0908339306eb
parent02b1fa07bb58f5d1f349b5b09eb936739a7b20fc (diff)
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: a42055e8d2c3 ("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>
-rw-r--r--include/net/tls.h5
-rw-r--r--net/tls/tls_device.c6
-rw-r--r--net/tls/tls_main.c2
-rw-r--r--net/tls/tls_sw.c21
4 files changed, 20 insertions, 14 deletions
diff --git a/include/net/tls.h b/include/net/tls.h
index c664e6dba0d1..794e297483ea 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -40,6 +40,7 @@
40#include <linux/socket.h> 40#include <linux/socket.h>
41#include <linux/tcp.h> 41#include <linux/tcp.h>
42#include <linux/skmsg.h> 42#include <linux/skmsg.h>
43#include <linux/mutex.h>
43#include <linux/netdevice.h> 44#include <linux/netdevice.h>
44#include <linux/rcupdate.h> 45#include <linux/rcupdate.h>
45 46
@@ -269,6 +270,10 @@ struct tls_context {
269 270
270 bool in_tcp_sendpages; 271 bool in_tcp_sendpages;
271 bool pending_open_record_frags; 272 bool pending_open_record_frags;
273
274 struct mutex tx_lock; /* protects partially_sent_* fields and
275 * per-type TX fields
276 */
272 unsigned long flags; 277 unsigned long flags;
273 278
274 /* cache cold stuff */ 279 /* cache cold stuff */
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index 5a3715ddc592..683d00837693 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -523,8 +523,10 @@ last_record:
523int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) 523int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
524{ 524{
525 unsigned char record_type = TLS_RECORD_TYPE_DATA; 525 unsigned char record_type = TLS_RECORD_TYPE_DATA;
526 struct tls_context *tls_ctx = tls_get_ctx(sk);
526 int rc; 527 int rc;
527 528
529 mutex_lock(&tls_ctx->tx_lock);
528 lock_sock(sk); 530 lock_sock(sk);
529 531
530 if (unlikely(msg->msg_controllen)) { 532 if (unlikely(msg->msg_controllen)) {
@@ -538,12 +540,14 @@ int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
538 540
539out: 541out:
540 release_sock(sk); 542 release_sock(sk);
543 mutex_unlock(&tls_ctx->tx_lock);
541 return rc; 544 return rc;
542} 545}
543 546
544int tls_device_sendpage(struct sock *sk, struct page *page, 547int tls_device_sendpage(struct sock *sk, struct page *page,
545 int offset, size_t size, int flags) 548 int offset, size_t size, int flags)
546{ 549{
550 struct tls_context *tls_ctx = tls_get_ctx(sk);
547 struct iov_iter msg_iter; 551 struct iov_iter msg_iter;
548 char *kaddr = kmap(page); 552 char *kaddr = kmap(page);
549 struct kvec iov; 553 struct kvec iov;
@@ -552,6 +556,7 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
552 if (flags & MSG_SENDPAGE_NOTLAST) 556 if (flags & MSG_SENDPAGE_NOTLAST)
553 flags |= MSG_MORE; 557 flags |= MSG_MORE;
554 558
559 mutex_lock(&tls_ctx->tx_lock);
555 lock_sock(sk); 560 lock_sock(sk);
556 561
557 if (flags & MSG_OOB) { 562 if (flags & MSG_OOB) {
@@ -568,6 +573,7 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
568 573
569out: 574out:
570 release_sock(sk); 575 release_sock(sk);
576 mutex_unlock(&tls_ctx->tx_lock);
571 return rc; 577 return rc;
572} 578}
573 579
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index ac88877dcade..0775ae40fcfb 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -267,6 +267,7 @@ void tls_ctx_free(struct sock *sk, struct tls_context *ctx)
267 267
268 memzero_explicit(&ctx->crypto_send, sizeof(ctx->crypto_send)); 268 memzero_explicit(&ctx->crypto_send, sizeof(ctx->crypto_send));
269 memzero_explicit(&ctx->crypto_recv, sizeof(ctx->crypto_recv)); 269 memzero_explicit(&ctx->crypto_recv, sizeof(ctx->crypto_recv));
270 mutex_destroy(&ctx->tx_lock);
270 271
271 if (sk) 272 if (sk)
272 kfree_rcu(ctx, rcu); 273 kfree_rcu(ctx, rcu);
@@ -612,6 +613,7 @@ static struct tls_context *create_ctx(struct sock *sk)
612 if (!ctx) 613 if (!ctx)
613 return NULL; 614 return NULL;
614 615
616 mutex_init(&ctx->tx_lock);
615 rcu_assign_pointer(icsk->icsk_ulp_data, ctx); 617 rcu_assign_pointer(icsk->icsk_ulp_data, ctx);
616 ctx->sk_proto = sk->sk_prot; 618 ctx->sk_proto = sk->sk_prot;
617 return ctx; 619 return ctx;
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index e155b792df0b..446f23c1f3ce 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -897,15 +897,9 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
897 if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL)) 897 if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL))
898 return -ENOTSUPP; 898 return -ENOTSUPP;
899 899
900 mutex_lock(&tls_ctx->tx_lock);
900 lock_sock(sk); 901 lock_sock(sk);
901 902
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
909 if (unlikely(msg->msg_controllen)) { 903 if (unlikely(msg->msg_controllen)) {
910 ret = tls_proccess_cmsg(sk, msg, &record_type); 904 ret = tls_proccess_cmsg(sk, msg, &record_type);
911 if (ret) { 905 if (ret) {
@@ -1091,6 +1085,7 @@ send_end:
1091 ret = sk_stream_error(sk, msg->msg_flags, ret); 1085 ret = sk_stream_error(sk, msg->msg_flags, ret);
1092 1086
1093 release_sock(sk); 1087 release_sock(sk);
1088 mutex_unlock(&tls_ctx->tx_lock);
1094 return copied ? copied : ret; 1089 return copied ? copied : ret;
1095} 1090}
1096 1091
@@ -1114,13 +1109,6 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page,
1114 eor = !(flags & (MSG_MORE | MSG_SENDPAGE_NOTLAST)); 1109 eor = !(flags & (MSG_MORE | MSG_SENDPAGE_NOTLAST));
1115 sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); 1110 sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
1116 1111
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
1124 /* Call the sk_stream functions to manage the sndbuf mem. */ 1112 /* Call the sk_stream functions to manage the sndbuf mem. */
1125 while (size > 0) { 1113 while (size > 0) {
1126 size_t copy, required_size; 1114 size_t copy, required_size;
@@ -1219,15 +1207,18 @@ sendpage_end:
1219int tls_sw_sendpage(struct sock *sk, struct page *page, 1207int tls_sw_sendpage(struct sock *sk, struct page *page,
1220 int offset, size_t size, int flags) 1208 int offset, size_t size, int flags)
1221{ 1209{
1210 struct tls_context *tls_ctx = tls_get_ctx(sk);
1222 int ret; 1211 int ret;
1223 1212
1224 if (flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL | 1213 if (flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL |
1225 MSG_SENDPAGE_NOTLAST | MSG_SENDPAGE_NOPOLICY)) 1214 MSG_SENDPAGE_NOTLAST | MSG_SENDPAGE_NOPOLICY))
1226 return -ENOTSUPP; 1215 return -ENOTSUPP;
1227 1216
1217 mutex_lock(&tls_ctx->tx_lock);
1228 lock_sock(sk); 1218 lock_sock(sk);
1229 ret = tls_sw_do_sendpage(sk, page, offset, size, flags); 1219 ret = tls_sw_do_sendpage(sk, page, offset, size, flags);
1230 release_sock(sk); 1220 release_sock(sk);
1221 mutex_unlock(&tls_ctx->tx_lock);
1231 return ret; 1222 return ret;
1232} 1223}
1233 1224
@@ -2170,9 +2161,11 @@ static void tx_work_handler(struct work_struct *work)
2170 2161
2171 if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) 2162 if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
2172 return; 2163 return;
2164 mutex_lock(&tls_ctx->tx_lock);
2173 lock_sock(sk); 2165 lock_sock(sk);
2174 tls_tx_records(sk, -1); 2166 tls_tx_records(sk, -1);
2175 release_sock(sk); 2167 release_sock(sk);
2168 mutex_unlock(&tls_ctx->tx_lock);
2176} 2169}
2177 2170
2178void tls_sw_write_space(struct sock *sk, struct tls_context *ctx) 2171void tls_sw_write_space(struct sock *sk, struct tls_context *ctx)