From: Sabrina Dubroca sd@queasysnail.net
[ Upstream commit 41532b785e9d79636b3815a64ddf6a096647d011 ]
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 aec7961 ("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 Link: https://lore.kernel.org/r/47bde5f649707610eaef9f0d679519966fc31061.170913264... Signed-off-by: Jakub Kicinski kuba@kernel.org [ William: The original patch did not apply cleanly due to deletions of non-existent lines in 6.1.y. The UAF the author stopped seeing can still be reproduced on systems without AVX in conjunction with cryptd. Also removed an extraneous statement after a return statement that is adjacent to diff. ] Link: https://lore.kernel.org/netdev/he2K1yz_u7bZ-CnYcTSQ4OxuLuHZXN6xZRgp6_ICSWnq8... Signed-off-by: William Liu will@willsroot.io --- Tested with original repro and all tests in selftests/net/tls.c --- net/tls/tls_sw.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 6ac3dcbe87b5..e1e3207168e3 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); @@ -289,7 +295,6 @@ static int tls_do_decryption(struct sock *sk, /* all completions have run, we're not doing async anymore */ darg->async = false; return ret; - ret = ret ?: -EINPROGRESS; }
atomic_dec(&ctx->decrypt_pending);