]> git.pld-linux.org Git - packages/kernel.git/commitdiff
- prevent deadlocks with xfs on dmcrypt in rare situations
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Fri, 7 Sep 2018 06:11:28 +0000 (08:11 +0200)
committerArkadiusz Miśkiewicz <arekm@maven.pl>
Fri, 7 Sep 2018 06:11:28 +0000 (08:11 +0200)
kernel-small_fixes.patch

index 7fdc8cdefd96e5e9e6391a6bd13730ba68622d0d..6edbd9d974d0e1b262b129f8568bdfd122af3838 100644 (file)
@@ -9,3 +9,110 @@
        echo 0
        exit 1
  fi
+From 432061b3da64e488be3403124a72a9250bbe96d4 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Wed, 5 Sep 2018 09:17:45 -0400
+Subject: dm: disable CRYPTO_TFM_REQ_MAY_SLEEP to fix a GFP_KERNEL recursion
+ deadlock
+
+There's a XFS on dm-crypt deadlock, recursing back to itself due to the
+crypto subsystems use of GFP_KERNEL, reported here:
+https://bugzilla.kernel.org/show_bug.cgi?id=200835
+
+* dm-crypt calls crypt_convert in xts mode
+* init_crypt from xts.c calls kmalloc(GFP_KERNEL)
+* kmalloc(GFP_KERNEL) recurses into the XFS filesystem, the filesystem
+       tries to submit some bios and wait for them, causing a deadlock
+
+Fix this by updating both the DM crypt and integrity targets to no
+longer use the CRYPTO_TFM_REQ_MAY_SLEEP flag, which will change the
+crypto allocations from GFP_KERNEL to GFP_ATOMIC, therefore they can't
+recurse into a filesystem.  A GFP_ATOMIC allocation can fail, but
+init_crypt() in xts.c handles the allocation failure gracefully - it
+will fall back to preallocated buffer if the allocation fails.
+
+The crypto API maintainer says that the crypto API only needs to
+allocate memory when dealing with unaligned buffers and therefore
+turning CRYPTO_TFM_REQ_MAY_SLEEP off is safe (see this discussion:
+https://www.redhat.com/archives/dm-devel/2018-August/msg00195.html )
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+---
+ drivers/md/dm-crypt.c     | 10 +++++-----
+ drivers/md/dm-integrity.c |  4 ++--
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
+index f266c81f396f..0481223b1deb 100644
+@@ -334,7 +334,7 @@ static int crypt_iv_essiv_init(struct cr
+       sg_init_one(&sg, cc->key, cc->key_size);
+       ahash_request_set_tfm(req, essiv->hash_tfm);
+-      ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
++      ahash_request_set_callback(req, 0, NULL, NULL);
+       ahash_request_set_crypt(req, &sg, essiv->salt, cc->key_size);
+       err = crypto_ahash_digest(req);
+@@ -606,7 +606,7 @@ static int crypt_iv_lmk_one(struct crypt_config *cc, u8 *iv,
+       int i, r;
+       desc->tfm = lmk->hash_tfm;
+-      desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
++      desc->flags = 0;
+       r = crypto_shash_init(desc);
+       if (r)
+@@ -768,7 +768,7 @@ static int crypt_iv_tcw_whitening(struct crypt_config *cc,
+       /* calculate crc32 for every 32bit part and xor it */
+       desc->tfm = tcw->crc32_tfm;
+-      desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
++      desc->flags = 0;
+       for (i = 0; i < 4; i++) {
+               r = crypto_shash_init(desc);
+               if (r)
+@@ -1251,7 +1251,7 @@ static void crypt_alloc_req_skcipher(struct crypt_config *cc,
+        * requests if driver request queue is full.
+        */
+       skcipher_request_set_callback(ctx->r.req,
+-          CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
++          CRYPTO_TFM_REQ_MAY_BACKLOG,
+           kcryptd_async_done, dmreq_of_req(cc, ctx->r.req));
+ }
+@@ -1268,7 +1268,7 @@ static void crypt_alloc_req_aead(struct crypt_config *cc,
+        * requests if driver request queue is full.
+        */
+       aead_request_set_callback(ctx->r.req_aead,
+-          CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
++          CRYPTO_TFM_REQ_MAY_BACKLOG,
+           kcryptd_async_done, dmreq_of_req(cc, ctx->r.req_aead));
+ }
+diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
+index 378878599466..89ccb64342de 100644
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -532,7 +532,7 @@ static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result
+       unsigned j, size;
+       desc->tfm = ic->journal_mac;
+-      desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
++      desc->flags = 0;
+       r = crypto_shash_init(desc);
+       if (unlikely(r)) {
+@@ -676,7 +676,7 @@ static void complete_journal_encrypt(struct crypto_async_request *req, int err)
+ static bool do_crypt(bool encrypt, struct skcipher_request *req, struct journal_completion *comp)
+ {
+       int r;
+-      skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
++      skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                     complete_journal_encrypt, comp);
+       if (likely(encrypt))
+               r = crypto_skcipher_encrypt(req);
+-- 
+cgit 1.2-0.3.lf.el7
+
This page took 0.057224 seconds and 4 git commands to generate.