* [PATCH net 0/4] tls: a few more fixes for async decrypt
@ 2024-02-28 22:43 Sabrina Dubroca
2024-02-28 22:43 ` [PATCH net 1/4] tls: decrement decrypt_pending if no async completion will be called Sabrina Dubroca
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Sabrina Dubroca @ 2024-02-28 22:43 UTC (permalink / raw)
To: netdev
Cc: Sabrina Dubroca, Vakul Garg, Boris Pismenny, John Fastabend,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman
The previous patchset [1] took care of "full async". This adds a few
fixes for cases where only part of the crypto operations go the async
route, found by extending my previous debug patch [2] to do N
synchronous operations followed by M asynchronous ops (with N and M
configurable).
[1] https://patchwork.kernel.org/project/netdevbpf/list/?series=823784&state=*
[2] https://lore.kernel.org/all/9d664093b1bf7f47497b2c40b3a085b45f3274a2.1694021240.git.sd@queasysnail.net/
Sabrina Dubroca (4):
tls: decrement decrypt_pending if no async completion will be called
tls: fix peeking with sync+async decryption
tls: separate no-async decryption request handling from async
tls: fix use-after-free on failed backlog decryption
net/tls/tls_sw.c | 40 +++++++++++++++++++++++++++++-----------
1 file changed, 29 insertions(+), 11 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net 1/4] tls: decrement decrypt_pending if no async completion will be called
2024-02-28 22:43 [PATCH net 0/4] tls: a few more fixes for async decrypt Sabrina Dubroca
@ 2024-02-28 22:43 ` Sabrina Dubroca
2024-02-28 22:43 ` [PATCH net 2/4] tls: fix peeking with sync+async decryption Sabrina Dubroca
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Sabrina Dubroca @ 2024-02-28 22:43 UTC (permalink / raw)
To: netdev
Cc: Sabrina Dubroca, Vakul Garg, Boris Pismenny, John Fastabend,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman
With mixed sync/async decryption, or failures of crypto_aead_decrypt,
we increment decrypt_pending but we never do the corresponding
decrement since tls_decrypt_done will not be called. In this case, we
should decrement decrypt_pending immediately to avoid getting stuck.
For example, the prequeue prequeue test gets stuck with mixed
modes (one async decrypt + one sync decrypt).
Fixes: 94524d8fc965 ("net/tls: Add support for async decryption of tls records")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
---
net/tls/tls_sw.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index de96959336c4..9f23ba321efe 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -289,6 +289,8 @@ static int tls_do_decryption(struct sock *sk,
return 0;
ret = crypto_wait_req(ret, &ctx->async_wait);
+ } else if (darg->async) {
+ atomic_dec(&ctx->decrypt_pending);
}
darg->async = false;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net 2/4] tls: fix peeking with sync+async decryption
2024-02-28 22:43 [PATCH net 0/4] tls: a few more fixes for async decrypt Sabrina Dubroca
2024-02-28 22:43 ` [PATCH net 1/4] tls: decrement decrypt_pending if no async completion will be called Sabrina Dubroca
@ 2024-02-28 22:43 ` Sabrina Dubroca
2024-02-28 22:43 ` [PATCH net 3/4] tls: separate no-async decryption request handling from async Sabrina Dubroca
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Sabrina Dubroca @ 2024-02-28 22:43 UTC (permalink / raw)
To: netdev
Cc: Sabrina Dubroca, Vakul Garg, Boris Pismenny, John Fastabend,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman
If we peek from 2 records with a currently empty rx_list, and the
first record is decrypted synchronously but the second record is
decrypted async, the following happens:
1. decrypt record 1 (sync)
2. copy from record 1 to the userspace's msg
3. queue the decrypted record to rx_list for future read(!PEEK)
4. decrypt record 2 (async)
5. queue record 2 to rx_list
6. call process_rx_list to copy data from the 2nd record
We currently pass copied=0 as skip offset to process_rx_list, so we
end up copying once again from the first record. We should skip over
the data we've already copied.
Seen with selftest tls.12_aes_gcm.recv_peek_large_buf_mult_recs
Fixes: 692d7b5d1f91 ("tls: Fix recvmsg() to be able to peek across multiple records")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
---
I'm not very happy with this, because the logic is already hard to
follow and I'm adding yet another variable counting how many bytes
we've handled, but everything else I tried broke at least one test
case :(
I'll see if I can rework this for net-next.
net/tls/tls_sw.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 9f23ba321efe..1394fc44f378 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1950,6 +1950,7 @@ int tls_sw_recvmsg(struct sock *sk,
struct strp_msg *rxm;
struct tls_msg *tlm;
ssize_t copied = 0;
+ ssize_t peeked = 0;
bool async = false;
int target, err;
bool is_kvec = iov_iter_is_kvec(&msg->msg_iter);
@@ -2097,8 +2098,10 @@ int tls_sw_recvmsg(struct sock *sk,
if (err < 0)
goto put_on_rx_list_err;
- if (is_peek)
+ if (is_peek) {
+ peeked += chunk;
goto put_on_rx_list;
+ }
if (partially_consumed) {
rxm->offset += chunk;
@@ -2137,8 +2140,8 @@ int tls_sw_recvmsg(struct sock *sk,
/* Drain records from the rx_list & copy if required */
if (is_peek || is_kvec)
- err = process_rx_list(ctx, msg, &control, copied,
- decrypted, is_peek, NULL);
+ err = process_rx_list(ctx, msg, &control, copied + peeked,
+ decrypted - peeked, is_peek, NULL);
else
err = process_rx_list(ctx, msg, &control, 0,
async_copy_bytes, is_peek, NULL);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net 3/4] tls: separate no-async decryption request handling from async
2024-02-28 22:43 [PATCH net 0/4] tls: a few more fixes for async decrypt Sabrina Dubroca
2024-02-28 22:43 ` [PATCH net 1/4] tls: decrement decrypt_pending if no async completion will be called Sabrina Dubroca
2024-02-28 22:43 ` [PATCH net 2/4] tls: fix peeking with sync+async decryption Sabrina Dubroca
@ 2024-02-28 22:43 ` Sabrina Dubroca
2024-02-28 22:44 ` [PATCH net 4/4] tls: fix use-after-free on failed backlog decryption Sabrina Dubroca
2024-02-29 17:20 ` [PATCH net 0/4] tls: a few more fixes for async decrypt patchwork-bot+netdevbpf
4 siblings, 0 replies; 6+ messages in thread
From: Sabrina Dubroca @ 2024-02-28 22:43 UTC (permalink / raw)
To: netdev
Cc: Sabrina Dubroca, Vakul Garg, Boris Pismenny, John Fastabend,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman
If we're not doing async, the handling is much simpler. There's no
reference counting, we just need to wait for the completion to wake us
up and return its result.
We should preferably also use a separate crypto_wait. I'm not seeing a
UAF as I did in the past, I think aec7961916f3 ("tls: fix race between
async notify and socket close") took care of it.
This will make the next fix easier.
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
---
net/tls/tls_sw.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 1394fc44f378..1fd37fe13ffd 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -274,9 +274,15 @@ static int tls_do_decryption(struct sock *sk,
DEBUG_NET_WARN_ON_ONCE(atomic_read(&ctx->decrypt_pending) < 1);
atomic_inc(&ctx->decrypt_pending);
} else {
+ DECLARE_CRYPTO_WAIT(wait);
+
aead_request_set_callback(aead_req,
CRYPTO_TFM_REQ_MAY_BACKLOG,
- crypto_req_done, &ctx->async_wait);
+ crypto_req_done, &wait);
+ ret = crypto_aead_decrypt(aead_req);
+ if (ret == -EINPROGRESS || ret == -EBUSY)
+ ret = crypto_wait_req(ret, &wait);
+ return ret;
}
ret = crypto_aead_decrypt(aead_req);
@@ -285,10 +291,7 @@ static int tls_do_decryption(struct sock *sk,
ret = ret ?: -EINPROGRESS;
}
if (ret == -EINPROGRESS) {
- if (darg->async)
- return 0;
-
- ret = crypto_wait_req(ret, &ctx->async_wait);
+ return 0;
} else if (darg->async) {
atomic_dec(&ctx->decrypt_pending);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net 4/4] tls: fix use-after-free on failed backlog decryption
2024-02-28 22:43 [PATCH net 0/4] tls: a few more fixes for async decrypt Sabrina Dubroca
` (2 preceding siblings ...)
2024-02-28 22:43 ` [PATCH net 3/4] tls: separate no-async decryption request handling from async Sabrina Dubroca
@ 2024-02-28 22:44 ` Sabrina Dubroca
2024-02-29 17:20 ` [PATCH net 0/4] tls: a few more fixes for async decrypt patchwork-bot+netdevbpf
4 siblings, 0 replies; 6+ messages in thread
From: Sabrina Dubroca @ 2024-02-28 22:44 UTC (permalink / raw)
To: netdev
Cc: Sabrina Dubroca, Vakul Garg, Boris Pismenny, John Fastabend,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman
When the decrypt request goes to the backlog and crypto_aead_decrypt
returns -EBUSY, tls_do_decryption will wait until all async
decryptions have completed. If one of them fails, tls_do_decryption
will return -EBADMSG and tls_decrypt_sg jumps to the error path,
releasing all the pages. But the pages have been passed to the async
callback, and have already been released by tls_decrypt_done.
The only true async case is when crypto_aead_decrypt returns
-EINPROGRESS. With -EBUSY, we already waited so we can tell
tls_sw_recvmsg that the data is available for immediate copy, but we
need to notify tls_decrypt_sg (via the new ->async_done flag) that the
memory has already been released.
Fixes: 859054147318 ("net: tls: handle backlogging of crypto requests")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
---
net/tls/tls_sw.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 1fd37fe13ffd..211f57164cb6 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -52,6 +52,7 @@ struct tls_decrypt_arg {
struct_group(inargs,
bool zc;
bool async;
+ bool async_done;
u8 tail;
);
@@ -286,15 +287,18 @@ static int tls_do_decryption(struct sock *sk,
}
ret = crypto_aead_decrypt(aead_req);
+ if (ret == -EINPROGRESS)
+ return 0;
+
if (ret == -EBUSY) {
ret = tls_decrypt_async_wait(ctx);
- ret = ret ?: -EINPROGRESS;
- }
- if (ret == -EINPROGRESS) {
- return 0;
- } else if (darg->async) {
- atomic_dec(&ctx->decrypt_pending);
+ darg->async_done = true;
+ /* all completions have run, we're not doing async anymore */
+ darg->async = false;
+ return ret;
}
+
+ atomic_dec(&ctx->decrypt_pending);
darg->async = false;
return ret;
@@ -1593,8 +1597,11 @@ static int tls_decrypt_sg(struct sock *sk, struct iov_iter *out_iov,
/* Prepare and submit AEAD request */
err = tls_do_decryption(sk, sgin, sgout, dctx->iv,
data_len + prot->tail_size, aead_req, darg);
- if (err)
+ if (err) {
+ if (darg->async_done)
+ goto exit_free_skb;
goto exit_free_pages;
+ }
darg->skb = clear_skb ?: tls_strp_msg(ctx);
clear_skb = NULL;
@@ -1606,6 +1613,9 @@ static int tls_decrypt_sg(struct sock *sk, struct iov_iter *out_iov,
return err;
}
+ if (unlikely(darg->async_done))
+ return 0;
+
if (prot->tail_size)
darg->tail = dctx->tail;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net 0/4] tls: a few more fixes for async decrypt
2024-02-28 22:43 [PATCH net 0/4] tls: a few more fixes for async decrypt Sabrina Dubroca
` (3 preceding siblings ...)
2024-02-28 22:44 ` [PATCH net 4/4] tls: fix use-after-free on failed backlog decryption Sabrina Dubroca
@ 2024-02-29 17:20 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+netdevbpf @ 2024-02-29 17:20 UTC (permalink / raw)
To: Sabrina Dubroca
Cc: netdev, vakul.garg, borisp, john.fastabend, kuba, davem, edumazet,
pabeni, horms
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 28 Feb 2024 23:43:56 +0100 you wrote:
> The previous patchset [1] took care of "full async". This adds a few
> fixes for cases where only part of the crypto operations go the async
> route, found by extending my previous debug patch [2] to do N
> synchronous operations followed by M asynchronous ops (with N and M
> configurable).
>
> [1] https://patchwork.kernel.org/project/netdevbpf/list/?series=823784&state=*
> [2] https://lore.kernel.org/all/9d664093b1bf7f47497b2c40b3a085b45f3274a2.1694021240.git.sd@queasysnail.net/
>
> [...]
Here is the summary with links:
- [net,1/4] tls: decrement decrypt_pending if no async completion will be called
https://git.kernel.org/netdev/net/c/f7fa16d49837
- [net,2/4] tls: fix peeking with sync+async decryption
https://git.kernel.org/netdev/net/c/6caaf104423d
- [net,3/4] tls: separate no-async decryption request handling from async
https://git.kernel.org/netdev/net/c/41532b785e9d
- [net,4/4] tls: fix use-after-free on failed backlog decryption
https://git.kernel.org/netdev/net/c/13114dc55430
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-02-29 17:20 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-28 22:43 [PATCH net 0/4] tls: a few more fixes for async decrypt Sabrina Dubroca
2024-02-28 22:43 ` [PATCH net 1/4] tls: decrement decrypt_pending if no async completion will be called Sabrina Dubroca
2024-02-28 22:43 ` [PATCH net 2/4] tls: fix peeking with sync+async decryption Sabrina Dubroca
2024-02-28 22:43 ` [PATCH net 3/4] tls: separate no-async decryption request handling from async Sabrina Dubroca
2024-02-28 22:44 ` [PATCH net 4/4] tls: fix use-after-free on failed backlog decryption Sabrina Dubroca
2024-02-29 17:20 ` [PATCH net 0/4] tls: a few more fixes for async decrypt patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).