Skip to content

Commit 0cada33

Browse files
vinaychelsiodavem330
authored andcommitted
net/tls: fix race condition causing kernel panic
tls_sw_recvmsg() and tls_decrypt_done() can be run concurrently. // tls_sw_recvmsg() if (atomic_read(&ctx->decrypt_pending)) crypto_wait_req(-EINPROGRESS, &ctx->async_wait); else reinit_completion(&ctx->async_wait.completion); //tls_decrypt_done() pending = atomic_dec_return(&ctx->decrypt_pending); if (!pending && READ_ONCE(ctx->async_notify)) complete(&ctx->async_wait.completion); Consider the scenario tls_decrypt_done() is about to run complete() if (!pending && READ_ONCE(ctx->async_notify)) and tls_sw_recvmsg() reads decrypt_pending == 0, does reinit_completion(), then tls_decrypt_done() runs complete(). This sequence of execution results in wrong completion. Consequently, for next decrypt request, it will not wait for completion, eventually on connection close, crypto resources freed, there is no way to handle pending decrypt response. This race condition can be avoided by having atomic_read() mutually exclusive with atomic_dec_return(),complete().Intoduced spin lock to ensure the mutual exclution. Addressed similar problem in tx direction. v1->v2: - More readable commit message. - Corrected the lock to fix new race scenario. - Removed barrier which is not needed now. Fixes: a42055e ("net/tls: Add support for async encryption of records for performance") Signed-off-by: Vinay Kumar Yadav <[email protected]> Reviewed-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 98790bb commit 0cada33

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

include/net/tls.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ struct tls_sw_context_tx {
135135
struct tls_rec *open_rec;
136136
struct list_head tx_list;
137137
atomic_t encrypt_pending;
138+
/* protect crypto_wait with encrypt_pending */
139+
spinlock_t encrypt_compl_lock;
138140
int async_notify;
139141
u8 async_capable:1;
140142

@@ -155,6 +157,8 @@ struct tls_sw_context_rx {
155157
u8 async_capable:1;
156158
u8 decrypted:1;
157159
atomic_t decrypt_pending;
160+
/* protect crypto_wait with decrypt_pending*/
161+
spinlock_t decrypt_compl_lock;
158162
bool async_notify;
159163
};
160164

net/tls/tls_sw.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,12 @@ static void tls_decrypt_done(struct crypto_async_request *req, int err)
206206

207207
kfree(aead_req);
208208

209+
spin_lock_bh(&ctx->decrypt_compl_lock);
209210
pending = atomic_dec_return(&ctx->decrypt_pending);
210211

211-
if (!pending && READ_ONCE(ctx->async_notify))
212+
if (!pending && ctx->async_notify)
212213
complete(&ctx->async_wait.completion);
214+
spin_unlock_bh(&ctx->decrypt_compl_lock);
213215
}
214216

215217
static int tls_do_decryption(struct sock *sk,
@@ -467,10 +469,12 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err)
467469
ready = true;
468470
}
469471

472+
spin_lock_bh(&ctx->encrypt_compl_lock);
470473
pending = atomic_dec_return(&ctx->encrypt_pending);
471474

472-
if (!pending && READ_ONCE(ctx->async_notify))
475+
if (!pending && ctx->async_notify)
473476
complete(&ctx->async_wait.completion);
477+
spin_unlock_bh(&ctx->encrypt_compl_lock);
474478

475479
if (!ready)
476480
return;
@@ -929,6 +933,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
929933
int num_zc = 0;
930934
int orig_size;
931935
int ret = 0;
936+
int pending;
932937

933938
if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL))
934939
return -EOPNOTSUPP;
@@ -1095,13 +1100,19 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
10951100
goto send_end;
10961101
} else if (num_zc) {
10971102
/* Wait for pending encryptions to get completed */
1098-
smp_store_mb(ctx->async_notify, true);
1103+
spin_lock_bh(&ctx->encrypt_compl_lock);
1104+
ctx->async_notify = true;
10991105

1100-
if (atomic_read(&ctx->encrypt_pending))
1106+
pending = atomic_read(&ctx->encrypt_pending);
1107+
spin_unlock_bh(&ctx->encrypt_compl_lock);
1108+
if (pending)
11011109
crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
11021110
else
11031111
reinit_completion(&ctx->async_wait.completion);
11041112

1113+
/* There can be no concurrent accesses, since we have no
1114+
* pending encrypt operations
1115+
*/
11051116
WRITE_ONCE(ctx->async_notify, false);
11061117

11071118
if (ctx->async_wait.err) {
@@ -1732,6 +1743,7 @@ int tls_sw_recvmsg(struct sock *sk,
17321743
bool is_kvec = iov_iter_is_kvec(&msg->msg_iter);
17331744
bool is_peek = flags & MSG_PEEK;
17341745
int num_async = 0;
1746+
int pending;
17351747

17361748
flags |= nonblock;
17371749

@@ -1894,8 +1906,11 @@ int tls_sw_recvmsg(struct sock *sk,
18941906
recv_end:
18951907
if (num_async) {
18961908
/* Wait for all previously submitted records to be decrypted */
1897-
smp_store_mb(ctx->async_notify, true);
1898-
if (atomic_read(&ctx->decrypt_pending)) {
1909+
spin_lock_bh(&ctx->decrypt_compl_lock);
1910+
ctx->async_notify = true;
1911+
pending = atomic_read(&ctx->decrypt_pending);
1912+
spin_unlock_bh(&ctx->decrypt_compl_lock);
1913+
if (pending) {
18991914
err = crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
19001915
if (err) {
19011916
/* one of async decrypt failed */
@@ -1907,6 +1922,10 @@ int tls_sw_recvmsg(struct sock *sk,
19071922
} else {
19081923
reinit_completion(&ctx->async_wait.completion);
19091924
}
1925+
1926+
/* There can be no concurrent accesses, since we have no
1927+
* pending decrypt operations
1928+
*/
19101929
WRITE_ONCE(ctx->async_notify, false);
19111930

19121931
/* Drain records from the rx_list & copy if required */
@@ -2293,6 +2312,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
22932312

22942313
if (tx) {
22952314
crypto_init_wait(&sw_ctx_tx->async_wait);
2315+
spin_lock_init(&sw_ctx_tx->encrypt_compl_lock);
22962316
crypto_info = &ctx->crypto_send.info;
22972317
cctx = &ctx->tx;
22982318
aead = &sw_ctx_tx->aead_send;
@@ -2301,6 +2321,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
23012321
sw_ctx_tx->tx_work.sk = sk;
23022322
} else {
23032323
crypto_init_wait(&sw_ctx_rx->async_wait);
2324+
spin_lock_init(&sw_ctx_rx->decrypt_compl_lock);
23042325
crypto_info = &ctx->crypto_recv.info;
23052326
cctx = &ctx->rx;
23062327
skb_queue_head_init(&sw_ctx_rx->rx_list);

0 commit comments

Comments
 (0)