tls: separate no-async decryption request handling from async
authorSabrina Dubroca <sd@queasysnail.net>
Wed, 28 Feb 2024 22:43:59 +0000 (23:43 +0100)
committerJakub Kicinski <kuba@kernel.org>
Thu, 29 Feb 2024 17:07:16 +0000 (09:07 -0800)
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>
Link: https://lore.kernel.org/r/47bde5f649707610eaef9f0d679519966fc31061.1709132643.git.sd@queasysnail.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/tls/tls_sw.c

index 1394fc44f378899cd04a4d0cae9304a581416dcd..1fd37fe13ffd8f12bb614d9fef8ab5d3ae363568 100644 (file)
@@ -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);
        }