diff mbox series

crypto: deflate - Make the acomp walk atomic

Message ID Z_4lh9uixqXsoXWr@gondor.apana.org.au
State New
Headers show
Series crypto: deflate - Make the acomp walk atomic | expand

Commit Message

Herbert Xu April 15, 2025, 9:23 a.m. UTC
On Tue, Apr 15, 2025 at 04:43:51PM +0800, kernel test robot wrote:
>
> +-------------------------------------------------------------------------+------------+------------+
> |                                                                         | 9c8cf58262 | 08cabc7d3c |
> +-------------------------------------------------------------------------+------------+------------+
> | BUG:sleeping_function_called_from_invalid_context_at_crypto/acompress.c | 0          | 18         |
> +-------------------------------------------------------------------------+------------+------------+

Thanks for the report.  This patch should fix it:

---8<---
Add an atomic flag to the acomp walk and use that in deflate.
Due to the use of a per-cpu context, it is impossible to sleep
during the walk in deflate.

Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202504151654.4c3b6393-lkp@intel.com
Fixes: 08cabc7d3c86 ("crypto: deflate - Convert to acomp")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff mbox series

Patch

diff --git a/crypto/acompress.c b/crypto/acompress.c
index 5d0b8b8b84f6..33c9c1af7407 100644
--- a/crypto/acompress.c
+++ b/crypto/acompress.c
@@ -622,7 +622,7 @@  int acomp_walk_next_dst(struct acomp_walk *walk)
 EXPORT_SYMBOL_GPL(acomp_walk_next_dst);
 
 int acomp_walk_virt(struct acomp_walk *__restrict walk,
-		    struct acomp_req *__restrict req)
+		    struct acomp_req *__restrict req, bool atomic)
 {
 	struct scatterlist *src = req->src;
 	struct scatterlist *dst = req->dst;
@@ -634,7 +634,7 @@  int acomp_walk_virt(struct acomp_walk *__restrict walk,
 		return -EINVAL;
 
 	walk->flags = 0;
-	if ((req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP))
+	if ((req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) && !atomic)
 		walk->flags |= ACOMP_WALK_SLEEP;
 	if ((req->base.flags & CRYPTO_ACOMP_REQ_SRC_VIRT))
 		walk->flags |= ACOMP_WALK_SRC_LINEAR;
diff --git a/crypto/deflate.c b/crypto/deflate.c
index bc76c343a0cf..dee2cf4e0d03 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -60,7 +60,7 @@  static int deflate_compress_one(struct acomp_req *req,
 	struct acomp_walk walk;
 	int ret;
 
-	ret = acomp_walk_virt(&walk, req);
+	ret = acomp_walk_virt(&walk, req, true);
 	if (ret)
 		return ret;
 
@@ -147,7 +147,7 @@  static int deflate_decompress_one(struct acomp_req *req,
 	struct acomp_walk walk;
 	int ret;
 
-	ret = acomp_walk_virt(&walk, req);
+	ret = acomp_walk_virt(&walk, req, true);
 	if (ret)
 		return ret;
 
diff --git a/include/crypto/internal/acompress.h b/include/crypto/internal/acompress.h
index fbbff9a8a2d9..2c461e16d238 100644
--- a/include/crypto/internal/acompress.h
+++ b/include/crypto/internal/acompress.h
@@ -228,7 +228,7 @@  void acomp_walk_done_dst(struct acomp_walk *walk, int used);
 int acomp_walk_next_src(struct acomp_walk *walk);
 int acomp_walk_next_dst(struct acomp_walk *walk);
 int acomp_walk_virt(struct acomp_walk *__restrict walk,
-		    struct acomp_req *__restrict req);
+		    struct acomp_req *__restrict req, bool atomic);
 
 static inline bool acomp_walk_more_src(const struct acomp_walk *walk, int cur)
 {