]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 22:18:31 +0000 (14:18 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 22:18:31 +0000 (14:18 -0800)
added patches:
crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch
crypto-algif_skcipher-do-not-assume-that-req-is-unchanged.patch
crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch
crypto-algif_skcipher-do-not-set-may_backlog-on-the-async-path.patch
crypto-atmel-sha-fix-atmel_sha_remove.patch
crypto-atmel-sha-remove-calls-of-clk_prepare-from-atomic-contexts.patch
crypto-marvell-cesa-fix-test-in-mv_cesa_dev_dma_init.patch
crypto-user-lock-crypto_alg_list-on-alg-dump.patch
evm-use-crypto_memneq-for-digest-comparisons.patch
rtlwifi-rtl8821ae-fix-5g-failure-when-eeprom-is-incorrectly-encoded.patch
rtlwifi-rtl8821ae-fix-errors-in-parameter-initialization.patch
zram-don-t-call-idr_remove-from-zram_remove.patch
zram-try-vmalloc-after-kmalloc.patch
zram-zcomp-use-gfp_noio-to-allocate-streams.patch
zsmalloc-fix-migrate_zspage-zs_free-race-condition.patch

16 files changed:
queue-4.4/crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch [new file with mode: 0644]
queue-4.4/crypto-algif_skcipher-do-not-assume-that-req-is-unchanged.patch [new file with mode: 0644]
queue-4.4/crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch [new file with mode: 0644]
queue-4.4/crypto-algif_skcipher-do-not-set-may_backlog-on-the-async-path.patch [new file with mode: 0644]
queue-4.4/crypto-atmel-sha-fix-atmel_sha_remove.patch [new file with mode: 0644]
queue-4.4/crypto-atmel-sha-remove-calls-of-clk_prepare-from-atomic-contexts.patch [new file with mode: 0644]
queue-4.4/crypto-marvell-cesa-fix-test-in-mv_cesa_dev_dma_init.patch [new file with mode: 0644]
queue-4.4/crypto-user-lock-crypto_alg_list-on-alg-dump.patch [new file with mode: 0644]
queue-4.4/evm-use-crypto_memneq-for-digest-comparisons.patch [new file with mode: 0644]
queue-4.4/rtlwifi-rtl8821ae-fix-5g-failure-when-eeprom-is-incorrectly-encoded.patch [new file with mode: 0644]
queue-4.4/rtlwifi-rtl8821ae-fix-errors-in-parameter-initialization.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/zram-don-t-call-idr_remove-from-zram_remove.patch [new file with mode: 0644]
queue-4.4/zram-try-vmalloc-after-kmalloc.patch [new file with mode: 0644]
queue-4.4/zram-zcomp-use-gfp_noio-to-allocate-streams.patch [new file with mode: 0644]
queue-4.4/zsmalloc-fix-migrate_zspage-zs_free-race-condition.patch [new file with mode: 0644]

diff --git a/queue-4.4/crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch b/queue-4.4/crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch
new file mode 100644 (file)
index 0000000..932ed71
--- /dev/null
@@ -0,0 +1,40 @@
+From fe09786178f9df713a4b2dd6b93c0a722346bf5e Mon Sep 17 00:00:00 2001
+From: "Wang, Rui Y" <rui.y.wang@intel.com>
+Date: Wed, 27 Jan 2016 17:08:37 +0800
+Subject: crypto: algif_hash - wait for crypto_ahash_init() to complete
+
+From: Wang, Rui Y <rui.y.wang@intel.com>
+
+commit fe09786178f9df713a4b2dd6b93c0a722346bf5e upstream.
+
+hash_sendmsg/sendpage() need to wait for the completion
+of crypto_ahash_init() otherwise it can cause panic.
+
+Signed-off-by: Rui Wang <rui.y.wang@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/algif_hash.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/crypto/algif_hash.c
++++ b/crypto/algif_hash.c
+@@ -54,7 +54,8 @@ static int hash_sendmsg(struct socket *s
+       lock_sock(sk);
+       if (!ctx->more) {
+-              err = crypto_ahash_init(&ctx->req);
++              err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
++                                              &ctx->completion);
+               if (err)
+                       goto unlock;
+       }
+@@ -125,6 +126,7 @@ static ssize_t hash_sendpage(struct sock
+       } else {
+               if (!ctx->more) {
+                       err = crypto_ahash_init(&ctx->req);
++                      err = af_alg_wait_for_completion(err, &ctx->completion);
+                       if (err)
+                               goto unlock;
+               }
diff --git a/queue-4.4/crypto-algif_skcipher-do-not-assume-that-req-is-unchanged.patch b/queue-4.4/crypto-algif_skcipher-do-not-assume-that-req-is-unchanged.patch
new file mode 100644 (file)
index 0000000..12f9aef
--- /dev/null
@@ -0,0 +1,150 @@
+From ec69bbfb9902c32a5c1492f2b1b8ad032a66d724 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Wed, 3 Feb 2016 21:39:24 +0800
+Subject: crypto: algif_skcipher - Do not assume that req is unchanged
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit ec69bbfb9902c32a5c1492f2b1b8ad032a66d724 upstream.
+
+The async path in algif_skcipher assumes that the crypto completion
+function will be called with the original request.  This is not
+necessarily the case.  In fact there is no need for this anyway
+since we already embed information into the request with struct
+skcipher_async_req.
+
+This patch adds a pointer to that struct and then passes it as
+the data to the callback function.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Tested-by: Tadeusz Struk <tadeusz.struk@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/algif_skcipher.c |   60 ++++++++++++++++++++++--------------------------
+ 1 file changed, 28 insertions(+), 32 deletions(-)
+
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -65,18 +65,10 @@ struct skcipher_async_req {
+       struct skcipher_async_rsgl first_sgl;
+       struct list_head list;
+       struct scatterlist *tsg;
+-      char iv[];
++      atomic_t *inflight;
++      struct skcipher_request req;
+ };
+-#define GET_SREQ(areq, ctx) (struct skcipher_async_req *)((char *)areq + \
+-      crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req)))
+-
+-#define GET_REQ_SIZE(ctx) \
+-      crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req))
+-
+-#define GET_IV_SIZE(ctx) \
+-      crypto_skcipher_ivsize(crypto_skcipher_reqtfm(&ctx->req))
+-
+ #define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
+                     sizeof(struct scatterlist) - 1)
+@@ -102,15 +94,12 @@ static void skcipher_free_async_sgls(str
+ static void skcipher_async_cb(struct crypto_async_request *req, int err)
+ {
+-      struct sock *sk = req->data;
+-      struct alg_sock *ask = alg_sk(sk);
+-      struct skcipher_ctx *ctx = ask->private;
+-      struct skcipher_async_req *sreq = GET_SREQ(req, ctx);
++      struct skcipher_async_req *sreq = req->data;
+       struct kiocb *iocb = sreq->iocb;
+-      atomic_dec(&ctx->inflight);
++      atomic_dec(sreq->inflight);
+       skcipher_free_async_sgls(sreq);
+-      kfree(req);
++      kzfree(sreq);
+       iocb->ki_complete(iocb, err, err);
+ }
+@@ -509,37 +498,42 @@ static int skcipher_recvmsg_async(struct
+ {
+       struct sock *sk = sock->sk;
+       struct alg_sock *ask = alg_sk(sk);
++      struct sock *psk = ask->parent;
++      struct alg_sock *pask = alg_sk(psk);
+       struct skcipher_ctx *ctx = ask->private;
++      struct skcipher_tfm *skc = pask->private;
++      struct crypto_skcipher *tfm = skc->skcipher;
+       struct skcipher_sg_list *sgl;
+       struct scatterlist *sg;
+       struct skcipher_async_req *sreq;
+       struct skcipher_request *req;
+       struct skcipher_async_rsgl *last_rsgl = NULL;
+       unsigned int txbufs = 0, len = 0, tx_nents = skcipher_all_sg_nents(ctx);
+-      unsigned int reqlen = sizeof(struct skcipher_async_req) +
+-                              GET_REQ_SIZE(ctx) + GET_IV_SIZE(ctx);
++      unsigned int reqsize = crypto_skcipher_reqsize(tfm);
++      unsigned int ivsize = crypto_skcipher_ivsize(tfm);
+       int err = -ENOMEM;
+       bool mark = false;
++      char *iv;
+-      lock_sock(sk);
+-      req = kmalloc(reqlen, GFP_KERNEL);
+-      if (unlikely(!req))
+-              goto unlock;
++      sreq = kzalloc(sizeof(*sreq) + reqsize + ivsize, GFP_KERNEL);
++      if (unlikely(!sreq))
++              goto out;
+-      sreq = GET_SREQ(req, ctx);
++      req = &sreq->req;
++      iv = (char *)(req + 1) + reqsize;
+       sreq->iocb = msg->msg_iocb;
+-      memset(&sreq->first_sgl, '\0', sizeof(struct skcipher_async_rsgl));
+       INIT_LIST_HEAD(&sreq->list);
++      sreq->inflight = &ctx->inflight;
++
++      lock_sock(sk);
+       sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL);
+-      if (unlikely(!sreq->tsg)) {
+-              kfree(req);
++      if (unlikely(!sreq->tsg))
+               goto unlock;
+-      }
+       sg_init_table(sreq->tsg, tx_nents);
+-      memcpy(sreq->iv, ctx->iv, GET_IV_SIZE(ctx));
+-      skcipher_request_set_tfm(req, crypto_skcipher_reqtfm(&ctx->req));
++      memcpy(iv, ctx->iv, ivsize);
++      skcipher_request_set_tfm(req, tfm);
+       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+-                                    skcipher_async_cb, sk);
++                                    skcipher_async_cb, sreq);
+       while (iov_iter_count(&msg->msg_iter)) {
+               struct skcipher_async_rsgl *rsgl;
+@@ -615,20 +609,22 @@ static int skcipher_recvmsg_async(struct
+               sg_mark_end(sreq->tsg + txbufs - 1);
+       skcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
+-                                 len, sreq->iv);
++                                 len, iv);
+       err = ctx->enc ? crypto_skcipher_encrypt(req) :
+                        crypto_skcipher_decrypt(req);
+       if (err == -EINPROGRESS) {
+               atomic_inc(&ctx->inflight);
+               err = -EIOCBQUEUED;
++              sreq = NULL;
+               goto unlock;
+       }
+ free:
+       skcipher_free_async_sgls(sreq);
+-      kfree(req);
+ unlock:
+       skcipher_wmem_wakeup(sk);
+       release_sock(sk);
++      kzfree(sreq);
++out:
+       return err;
+ }
diff --git a/queue-4.4/crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch b/queue-4.4/crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch
new file mode 100644 (file)
index 0000000..c069e32
--- /dev/null
@@ -0,0 +1,70 @@
+From 6454c2b83f719057069777132b13949e4c6b6350 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Wed, 3 Feb 2016 21:39:26 +0800
+Subject: crypto: algif_skcipher - Do not dereference ctx without socket lock
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit 6454c2b83f719057069777132b13949e4c6b6350 upstream.
+
+Any access to non-constant bits of the private context must be
+done under the socket lock, in particular, this includes ctx->req.
+
+This patch moves such accesses under the lock, and fetches the
+tfm from the parent socket which is guaranteed to be constant,
+rather than from ctx->req.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/algif_skcipher.c |   15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -295,8 +295,11 @@ static int skcipher_sendmsg(struct socke
+ {
+       struct sock *sk = sock->sk;
+       struct alg_sock *ask = alg_sk(sk);
++      struct sock *psk = ask->parent;
++      struct alg_sock *pask = alg_sk(psk);
+       struct skcipher_ctx *ctx = ask->private;
+-      struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(&ctx->req);
++      struct skcipher_tfm *skc = pask->private;
++      struct crypto_skcipher *tfm = skc->skcipher;
+       unsigned ivsize = crypto_skcipher_ivsize(tfm);
+       struct skcipher_sg_list *sgl;
+       struct af_alg_control con = {};
+@@ -508,7 +511,7 @@ static int skcipher_recvmsg_async(struct
+       struct skcipher_async_req *sreq;
+       struct skcipher_request *req;
+       struct skcipher_async_rsgl *last_rsgl = NULL;
+-      unsigned int txbufs = 0, len = 0, tx_nents = skcipher_all_sg_nents(ctx);
++      unsigned int txbufs = 0, len = 0, tx_nents;
+       unsigned int reqsize = crypto_skcipher_reqsize(tfm);
+       unsigned int ivsize = crypto_skcipher_ivsize(tfm);
+       int err = -ENOMEM;
+@@ -526,6 +529,7 @@ static int skcipher_recvmsg_async(struct
+       sreq->inflight = &ctx->inflight;
+       lock_sock(sk);
++      tx_nents = skcipher_all_sg_nents(ctx);
+       sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL);
+       if (unlikely(!sreq->tsg))
+               goto unlock;
+@@ -633,9 +637,12 @@ static int skcipher_recvmsg_sync(struct
+ {
+       struct sock *sk = sock->sk;
+       struct alg_sock *ask = alg_sk(sk);
++      struct sock *psk = ask->parent;
++      struct alg_sock *pask = alg_sk(psk);
+       struct skcipher_ctx *ctx = ask->private;
+-      unsigned bs = crypto_skcipher_blocksize(crypto_skcipher_reqtfm(
+-              &ctx->req));
++      struct skcipher_tfm *skc = pask->private;
++      struct crypto_skcipher *tfm = skc->skcipher;
++      unsigned bs = crypto_skcipher_blocksize(tfm);
+       struct skcipher_sg_list *sgl;
+       struct scatterlist *sg;
+       int err = -EAGAIN;
diff --git a/queue-4.4/crypto-algif_skcipher-do-not-set-may_backlog-on-the-async-path.patch b/queue-4.4/crypto-algif_skcipher-do-not-set-may_backlog-on-the-async-path.patch
new file mode 100644 (file)
index 0000000..604ad0a
--- /dev/null
@@ -0,0 +1,41 @@
+From dad41997063723eaf5f77bc2015606a5a9bce320 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Wed, 3 Feb 2016 21:39:27 +0800
+Subject: crypto: algif_skcipher - Do not set MAY_BACKLOG on the async path
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit dad41997063723eaf5f77bc2015606a5a9bce320 upstream.
+
+The async path cannot use MAY_BACKLOG because it is not meant to
+block, which is what MAY_BACKLOG does.  On the other hand, both
+the sync and async paths can make use of MAY_SLEEP.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/algif_skcipher.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -536,7 +536,7 @@ static int skcipher_recvmsg_async(struct
+       sg_init_table(sreq->tsg, tx_nents);
+       memcpy(iv, ctx->iv, ivsize);
+       skcipher_request_set_tfm(req, tfm);
+-      skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
++      skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
+                                     skcipher_async_cb, sreq);
+       while (iov_iter_count(&msg->msg_iter)) {
+@@ -950,7 +950,8 @@ static int skcipher_accept_parent_nokey(
+       ask->private = ctx;
+       skcipher_request_set_tfm(&ctx->req, skcipher);
+-      skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
++      skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_SLEEP |
++                                               CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                     af_alg_complete, &ctx->completion);
+       sk->sk_destruct = skcipher_sock_destruct;
diff --git a/queue-4.4/crypto-atmel-sha-fix-atmel_sha_remove.patch b/queue-4.4/crypto-atmel-sha-fix-atmel_sha_remove.patch
new file mode 100644 (file)
index 0000000..39bb9b2
--- /dev/null
@@ -0,0 +1,37 @@
+From d961436c11482e974b702c8324426208f00cd7c4 Mon Sep 17 00:00:00 2001
+From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
+Date: Fri, 5 Feb 2016 13:45:12 +0100
+Subject: crypto: atmel-sha - fix atmel_sha_remove()
+
+From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
+
+commit d961436c11482e974b702c8324426208f00cd7c4 upstream.
+
+Since atmel_sha_probe() uses devm_xxx functions to allocate resources,
+atmel_sha_remove() should no longer explicitly release them.
+
+Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
+Fixes: b0e8b3417a62 ("crypto: atmel - use devm_xxx() managed function")
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/crypto/atmel-sha.c |    7 -------
+ 1 file changed, 7 deletions(-)
+
+--- a/drivers/crypto/atmel-sha.c
++++ b/drivers/crypto/atmel-sha.c
+@@ -1484,13 +1484,6 @@ static int atmel_sha_remove(struct platf
+       if (sha_dd->caps.has_dma)
+               atmel_sha_dma_cleanup(sha_dd);
+-      iounmap(sha_dd->io_base);
+-
+-      clk_put(sha_dd->iclk);
+-
+-      if (sha_dd->irq >= 0)
+-              free_irq(sha_dd->irq, sha_dd);
+-
+       return 0;
+ }
diff --git a/queue-4.4/crypto-atmel-sha-remove-calls-of-clk_prepare-from-atomic-contexts.patch b/queue-4.4/crypto-atmel-sha-remove-calls-of-clk_prepare-from-atomic-contexts.patch
new file mode 100644 (file)
index 0000000..c6e76e7
--- /dev/null
@@ -0,0 +1,99 @@
+From c033042aa8f69894df37dabcaa0231594834a4e4 Mon Sep 17 00:00:00 2001
+From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
+Date: Fri, 5 Feb 2016 13:45:13 +0100
+Subject: crypto: atmel-sha - remove calls of clk_prepare() from atomic contexts
+
+From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
+
+commit c033042aa8f69894df37dabcaa0231594834a4e4 upstream.
+
+clk_prepare()/clk_unprepare() must not be called within atomic context.
+
+This patch calls clk_prepare() once for all from atmel_sha_probe() and
+clk_unprepare() from atmel_sha_remove().
+
+Then calls of clk_prepare_enable()/clk_disable_unprepare() were replaced
+by calls of clk_enable()/clk_disable().
+
+Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
+Reported-by: Matthias Mayr <matthias.mayr@student.kit.edu>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/crypto/atmel-sha.c |   18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+--- a/drivers/crypto/atmel-sha.c
++++ b/drivers/crypto/atmel-sha.c
+@@ -783,7 +783,7 @@ static void atmel_sha_finish_req(struct
+       dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
+                       SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
+-      clk_disable_unprepare(dd->iclk);
++      clk_disable(dd->iclk);
+       if (req->base.complete)
+               req->base.complete(&req->base, err);
+@@ -796,7 +796,7 @@ static int atmel_sha_hw_init(struct atme
+ {
+       int err;
+-      err = clk_prepare_enable(dd->iclk);
++      err = clk_enable(dd->iclk);
+       if (err)
+               return err;
+@@ -823,7 +823,7 @@ static void atmel_sha_hw_version_init(st
+       dev_info(dd->dev,
+                       "version: 0x%x\n", dd->hw_version);
+-      clk_disable_unprepare(dd->iclk);
++      clk_disable(dd->iclk);
+ }
+ static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
+@@ -1411,6 +1411,10 @@ static int atmel_sha_probe(struct platfo
+               goto res_err;
+       }
++      err = clk_prepare(sha_dd->iclk);
++      if (err)
++              goto res_err;
++
+       atmel_sha_hw_version_init(sha_dd);
+       atmel_sha_get_cap(sha_dd);
+@@ -1422,12 +1426,12 @@ static int atmel_sha_probe(struct platfo
+                       if (IS_ERR(pdata)) {
+                               dev_err(&pdev->dev, "platform data not available\n");
+                               err = PTR_ERR(pdata);
+-                              goto res_err;
++                              goto iclk_unprepare;
+                       }
+               }
+               if (!pdata->dma_slave) {
+                       err = -ENXIO;
+-                      goto res_err;
++                      goto iclk_unprepare;
+               }
+               err = atmel_sha_dma_init(sha_dd, pdata);
+               if (err)
+@@ -1458,6 +1462,8 @@ err_algs:
+       if (sha_dd->caps.has_dma)
+               atmel_sha_dma_cleanup(sha_dd);
+ err_sha_dma:
++iclk_unprepare:
++      clk_unprepare(sha_dd->iclk);
+ res_err:
+       tasklet_kill(&sha_dd->done_task);
+ sha_dd_err:
+@@ -1484,6 +1490,8 @@ static int atmel_sha_remove(struct platf
+       if (sha_dd->caps.has_dma)
+               atmel_sha_dma_cleanup(sha_dd);
++      clk_unprepare(sha_dd->iclk);
++
+       return 0;
+ }
diff --git a/queue-4.4/crypto-marvell-cesa-fix-test-in-mv_cesa_dev_dma_init.patch b/queue-4.4/crypto-marvell-cesa-fix-test-in-mv_cesa_dev_dma_init.patch
new file mode 100644 (file)
index 0000000..89cf609
--- /dev/null
@@ -0,0 +1,31 @@
+From 8a3978ad55fb4c0564d285fb2f6cdee2313fce01 Mon Sep 17 00:00:00 2001
+From: Boris BREZILLON <boris.brezillon@free-electrons.com>
+Date: Fri, 5 Feb 2016 17:45:48 +0100
+Subject: crypto: marvell/cesa - fix test in mv_cesa_dev_dma_init()
+
+From: Boris BREZILLON <boris.brezillon@free-electrons.com>
+
+commit 8a3978ad55fb4c0564d285fb2f6cdee2313fce01 upstream.
+
+We are checking twice if dma->cache_pool is not NULL but are never testing
+dma->padding_pool value.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/crypto/marvell/cesa.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/crypto/marvell/cesa.c
++++ b/drivers/crypto/marvell/cesa.c
+@@ -306,7 +306,7 @@ static int mv_cesa_dev_dma_init(struct m
+               return -ENOMEM;
+       dma->padding_pool = dmam_pool_create("cesa_padding", dev, 72, 1, 0);
+-      if (!dma->cache_pool)
++      if (!dma->padding_pool)
+               return -ENOMEM;
+       cesa->dma = dma;
diff --git a/queue-4.4/crypto-user-lock-crypto_alg_list-on-alg-dump.patch b/queue-4.4/crypto-user-lock-crypto_alg_list-on-alg-dump.patch
new file mode 100644 (file)
index 0000000..bc0059d
--- /dev/null
@@ -0,0 +1,99 @@
+From 63e41ebc6630f39422d87f8a4bade1e793f37a01 Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli@googlemail.com>
+Date: Mon, 1 Feb 2016 14:27:30 +0100
+Subject: crypto: user - lock crypto_alg_list on alg dump
+
+From: Mathias Krause <minipli@googlemail.com>
+
+commit 63e41ebc6630f39422d87f8a4bade1e793f37a01 upstream.
+
+We miss to take the crypto_alg_sem semaphore when traversing the
+crypto_alg_list for CRYPTO_MSG_GETALG dumps. This allows a race with
+crypto_unregister_alg() removing algorithms from the list while we're
+still traversing it, thereby leading to a use-after-free as show below:
+
+[ 3482.071639] general protection fault: 0000 [#1] SMP
+[ 3482.075639] Modules linked in: aes_x86_64 glue_helper lrw ablk_helper cryptd gf128mul ipv6 pcspkr serio_raw virtio_net microcode virtio_pci virtio_ring virtio sr_mod cdrom [last unloaded: aesni_intel]
+[ 3482.075639] CPU: 1 PID: 11065 Comm: crconf Not tainted 4.3.4-grsec+ #126
+[ 3482.075639] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014
+[ 3482.075639] task: ffff88001cd41a40 ti: ffff88001cd422c8 task.ti: ffff88001cd422c8
+[ 3482.075639] RIP: 0010:[<ffffffff93722bd3>]  [<ffffffff93722bd3>] strncpy+0x13/0x30
+[ 3482.075639] RSP: 0018:ffff88001f713b60  EFLAGS: 00010202
+[ 3482.075639] RAX: ffff88001f6c4430 RBX: ffff88001f6c43a0 RCX: ffff88001f6c4430
+[ 3482.075639] RDX: 0000000000000040 RSI: fefefefefefeff16 RDI: ffff88001f6c4430
+[ 3482.075639] RBP: ffff88001f713b60 R08: ffff88001f6c4470 R09: ffff88001f6c4480
+[ 3482.075639] R10: 0000000000000002 R11: 0000000000000246 R12: ffff88001ce2aa28
+[ 3482.075639] R13: ffff880000093700 R14: ffff88001f5e4bf8 R15: 0000000000003b20
+[ 3482.075639] FS:  0000033826fa2700(0000) GS:ffff88001e900000(0000) knlGS:0000000000000000
+[ 3482.075639] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 3482.075639] CR2: ffffffffff600400 CR3: 00000000139ec000 CR4: 00000000001606f0
+[ 3482.075639] Stack:
+[ 3482.075639]  ffff88001f713bd8 ffffffff936ccd00 ffff88001e5c4200 ffff880000093700
+[ 3482.075639]  ffff88001f713bd0 ffffffff938ef4bf 0000000000000000 0000000000003b20
+[ 3482.075639]  ffff88001f5e4bf8 ffff88001f5e4848 0000000000000000 0000000000003b20
+[ 3482.075639] Call Trace:
+[ 3482.075639]  [<ffffffff936ccd00>] crypto_report_alg+0xc0/0x3e0
+[ 3482.075639]  [<ffffffff938ef4bf>] ? __alloc_skb+0x16f/0x300
+[ 3482.075639]  [<ffffffff936cd08a>] crypto_dump_report+0x6a/0x90
+[ 3482.075639]  [<ffffffff93935707>] netlink_dump+0x147/0x2e0
+[ 3482.075639]  [<ffffffff93935f99>] __netlink_dump_start+0x159/0x190
+[ 3482.075639]  [<ffffffff936ccb13>] crypto_user_rcv_msg+0xc3/0x130
+[ 3482.075639]  [<ffffffff936cd020>] ? crypto_report_alg+0x3e0/0x3e0
+[ 3482.075639]  [<ffffffff936cc4b0>] ? alg_test_crc32c+0x120/0x120
+[ 3482.075639]  [<ffffffff93933145>] ? __netlink_lookup+0xd5/0x120
+[ 3482.075639]  [<ffffffff936cca50>] ? crypto_add_alg+0x1d0/0x1d0
+[ 3482.075639]  [<ffffffff93938141>] netlink_rcv_skb+0xe1/0x130
+[ 3482.075639]  [<ffffffff936cc4f8>] crypto_netlink_rcv+0x28/0x40
+[ 3482.075639]  [<ffffffff939375a8>] netlink_unicast+0x108/0x180
+[ 3482.075639]  [<ffffffff93937c21>] netlink_sendmsg+0x541/0x770
+[ 3482.075639]  [<ffffffff938e31e1>] sock_sendmsg+0x21/0x40
+[ 3482.075639]  [<ffffffff938e4763>] SyS_sendto+0xf3/0x130
+[ 3482.075639]  [<ffffffff93444203>] ? bad_area_nosemaphore+0x13/0x20
+[ 3482.075639]  [<ffffffff93444470>] ? __do_page_fault+0x80/0x3a0
+[ 3482.075639]  [<ffffffff939d80cb>] entry_SYSCALL_64_fastpath+0x12/0x6e
+[ 3482.075639] Code: 88 4a ff 75 ed 5d 48 0f ba 2c 24 3f c3 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 85 d2 48 89 f8 48 89 f9 4c 8d 04 17 48 89 e5 74 15 <0f> b6 16 80 fa 01 88 11 48 83 de ff 48 83 c1 01 4c 39 c1 75 eb
+[ 3482.075639] RIP  [<ffffffff93722bd3>] strncpy+0x13/0x30
+
+To trigger the race run the following loops simultaneously for a while:
+  $ while : ; do modprobe aesni-intel; rmmod aesni-intel; done
+  $ while : ; do crconf show all > /dev/null; done
+
+Fix the race by taking the crypto_alg_sem read lock, thereby preventing
+crypto_unregister_alg() from modifying the algorithm list during the
+dump.
+
+This bug has been detected by the PaX memory sanitize feature.
+
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Cc: PaX Team <pageexec@freemail.hu>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/crypto_user.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/crypto/crypto_user.c
++++ b/crypto/crypto_user.c
+@@ -499,6 +499,7 @@ static int crypto_user_rcv_msg(struct sk
+               if (link->dump == NULL)
+                       return -EINVAL;
++              down_read(&crypto_alg_sem);
+               list_for_each_entry(alg, &crypto_alg_list, cra_list)
+                       dump_alloc += CRYPTO_REPORT_MAXSIZE;
+@@ -508,8 +509,11 @@ static int crypto_user_rcv_msg(struct sk
+                               .done = link->done,
+                               .min_dump_alloc = dump_alloc,
+                       };
+-                      return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
++                      err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
+               }
++              up_read(&crypto_alg_sem);
++
++              return err;
+       }
+       err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
diff --git a/queue-4.4/evm-use-crypto_memneq-for-digest-comparisons.patch b/queue-4.4/evm-use-crypto_memneq-for-digest-comparisons.patch
new file mode 100644 (file)
index 0000000..0c36da3
--- /dev/null
@@ -0,0 +1,44 @@
+From 613317bd212c585c20796c10afe5daaa95d4b0a1 Mon Sep 17 00:00:00 2001
+From: Ryan Ware <ware@linux.intel.com>
+Date: Thu, 11 Feb 2016 15:58:44 -0800
+Subject: EVM: Use crypto_memneq() for digest comparisons
+
+From: Ryan Ware <ware@linux.intel.com>
+
+commit 613317bd212c585c20796c10afe5daaa95d4b0a1 upstream.
+
+This patch fixes vulnerability CVE-2016-2085.  The problem exists
+because the vm_verify_hmac() function includes a use of memcmp().
+Unfortunately, this allows timing side channel attacks; specifically
+a MAC forgery complexity drop from 2^128 to 2^12.  This patch changes
+the memcmp() to the cryptographically safe crypto_memneq().
+
+Reported-by: Xiaofei Rex Guo <xiaofei.rex.guo@intel.com>
+Signed-off-by: Ryan Ware <ware@linux.intel.com>
+Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
+Signed-off-by: James Morris <james.l.morris@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ security/integrity/evm/evm_main.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/security/integrity/evm/evm_main.c
++++ b/security/integrity/evm/evm_main.c
+@@ -23,6 +23,7 @@
+ #include <linux/integrity.h>
+ #include <linux/evm.h>
+ #include <crypto/hash.h>
++#include <crypto/algapi.h>
+ #include "evm.h"
+ int evm_initialized;
+@@ -148,7 +149,7 @@ static enum integrity_status evm_verify_
+                                  xattr_value_len, calc.digest);
+               if (rc)
+                       break;
+-              rc = memcmp(xattr_data->digest, calc.digest,
++              rc = crypto_memneq(xattr_data->digest, calc.digest,
+                           sizeof(calc.digest));
+               if (rc)
+                       rc = -EINVAL;
diff --git a/queue-4.4/rtlwifi-rtl8821ae-fix-5g-failure-when-eeprom-is-incorrectly-encoded.patch b/queue-4.4/rtlwifi-rtl8821ae-fix-5g-failure-when-eeprom-is-incorrectly-encoded.patch
new file mode 100644 (file)
index 0000000..c61003b
--- /dev/null
@@ -0,0 +1,55 @@
+From c72fc9093718a3f8597249863a1bac345ba00859 Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Wed, 20 Jan 2016 21:58:39 -0600
+Subject: rtlwifi: rtl8821ae: Fix 5G failure when EEPROM is incorrectly encoded
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit c72fc9093718a3f8597249863a1bac345ba00859 upstream.
+
+Recently, it has been reported that D-Link DWA-582 cards, which use an
+RTL8812AE chip are not able to scan for 5G networks. The problems started
+with kernel 4.2, which is the first version that had commit d10101a60372
+("rtlwifi: rtl8821ae: Fix problem with regulatory information"). With this
+patch, the driver went from setting a default channel plan to using
+the value derived from EEPROM.
+
+Bug reports at https://bugzilla.kernel.org/show_bug.cgi?id=111031 and
+https://bugzilla.redhat.com/show_bug.cgi?id=1279653 are examples of this
+problem.
+
+The problem was solved once I learned that the internal country code was
+resulting in a regulatory set with only 2.4 GHz channels. With the RTL8821AE
+chips available to me, the country code was such that both 2.4 and 5 GHz
+channels are allowed. The fix is to allow both bands even when the EEPROM
+is incorrectly encoded.
+
+Fixes: d10101a60372 ("rtlwifi: rtl8821ae: Fix problem with regulatory information")
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Cc: littlesmartguy@gmail.com
+Cc: gabe@codehaus.org
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/realtek/rtlwifi/regd.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/realtek/rtlwifi/regd.c
++++ b/drivers/net/wireless/realtek/rtlwifi/regd.c
+@@ -351,7 +351,6 @@ static const struct ieee80211_regdomain
+       case COUNTRY_CODE_SPAIN:
+       case COUNTRY_CODE_FRANCE:
+       case COUNTRY_CODE_ISRAEL:
+-      case COUNTRY_CODE_WORLD_WIDE_13:
+               return &rtl_regdom_12_13;
+       case COUNTRY_CODE_MKK:
+       case COUNTRY_CODE_MKK1:
+@@ -360,6 +359,7 @@ static const struct ieee80211_regdomain
+               return &rtl_regdom_14_60_64;
+       case COUNTRY_CODE_GLOBAL_DOMAIN:
+               return &rtl_regdom_14;
++      case COUNTRY_CODE_WORLD_WIDE_13:
+       case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL:
+               return &rtl_regdom_12_13_5g_all;
+       default:
diff --git a/queue-4.4/rtlwifi-rtl8821ae-fix-errors-in-parameter-initialization.patch b/queue-4.4/rtlwifi-rtl8821ae-fix-errors-in-parameter-initialization.patch
new file mode 100644 (file)
index 0000000..d7b1de4
--- /dev/null
@@ -0,0 +1,52 @@
+From 78bae1de422a7f6f2b4b61f6a5c379e3d7f96f44 Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Mon, 14 Dec 2015 16:34:33 -0600
+Subject: rtlwifi: rtl8821ae: Fix errors in parameter initialization
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit 78bae1de422a7f6f2b4b61f6a5c379e3d7f96f44 upstream.
+
+This driver failed to copy parameters sw_crypto and disable_watchdog into
+the locations actually used by the driver. In addition, msi_support was
+initialized three times and one of them used the wrong variable. The
+initialization of parameter int_clear was moved so that it is near that
+of the rest of the parameters.
+
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+@@ -95,8 +95,6 @@ int rtl8821ae_init_sw_vars(struct ieee80
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       rtl8821ae_bt_reg_init(hw);
+-      rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+-      rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
+       rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
+       rtlpriv->dm.dm_initialgain_enable = 1;
+@@ -168,12 +166,15 @@ int rtl8821ae_init_sw_vars(struct ieee80
+       rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
+       rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+       rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+-      rtlpci->msi_support = rtlpriv->cfg->mod_params->int_clear;
++      rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
++      rtlpriv->cfg->mod_params->sw_crypto =
++              rtlpriv->cfg->mod_params->sw_crypto;
++      rtlpriv->cfg->mod_params->disable_watchdog =
++              rtlpriv->cfg->mod_params->disable_watchdog;
+       if (rtlpriv->cfg->mod_params->disable_watchdog)
+               pr_info("watchdog disabled\n");
+       rtlpriv->psc.reg_fwctrl_lps = 3;
+       rtlpriv->psc.reg_max_lps_awakeintvl = 5;
+-      rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+       /* for ASPM, you can close aspm through
+        * set const_support_pciaspm = 0
index 6df059ba0df82319b5d2adc8f772ff9a0de8fdc2..b474adcc05edcd8a0237a1dac6a7c2d78b40af7e 100644 (file)
@@ -100,3 +100,18 @@ crypto-algif_skcipher-sendmsg-sg-marking-is-off-by-one.patch
 crypto-caam-make-write-transactions-bufferable-on-ppc-platforms.patch
 crypto-chacha20-ssse3-align-stack-pointer-to-64-bytes.patch
 crypto-shash-fix-has_key-setting.patch
+crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch
+evm-use-crypto_memneq-for-digest-comparisons.patch
+crypto-user-lock-crypto_alg_list-on-alg-dump.patch
+crypto-algif_skcipher-do-not-assume-that-req-is-unchanged.patch
+crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch
+crypto-algif_skcipher-do-not-set-may_backlog-on-the-async-path.patch
+crypto-atmel-sha-fix-atmel_sha_remove.patch
+crypto-atmel-sha-remove-calls-of-clk_prepare-from-atomic-contexts.patch
+crypto-marvell-cesa-fix-test-in-mv_cesa_dev_dma_init.patch
+rtlwifi-rtl8821ae-fix-errors-in-parameter-initialization.patch
+rtlwifi-rtl8821ae-fix-5g-failure-when-eeprom-is-incorrectly-encoded.patch
+zram-zcomp-use-gfp_noio-to-allocate-streams.patch
+zram-try-vmalloc-after-kmalloc.patch
+zram-don-t-call-idr_remove-from-zram_remove.patch
+zsmalloc-fix-migrate_zspage-zs_free-race-condition.patch
diff --git a/queue-4.4/zram-don-t-call-idr_remove-from-zram_remove.patch b/queue-4.4/zram-don-t-call-idr_remove-from-zram_remove.patch
new file mode 100644 (file)
index 0000000..c594cdf
--- /dev/null
@@ -0,0 +1,54 @@
+From 17ec4cd985780a7e30aa45bb8f272237c12502a4 Mon Sep 17 00:00:00 2001
+From: Jerome Marchand <jmarchan@redhat.com>
+Date: Fri, 15 Jan 2016 16:54:48 -0800
+Subject: zram: don't call idr_remove() from zram_remove()
+
+From: Jerome Marchand <jmarchan@redhat.com>
+
+commit 17ec4cd985780a7e30aa45bb8f272237c12502a4 upstream.
+
+The use of idr_remove() is forbidden in the callback functions of
+idr_for_each().  It is therefore unsafe to call idr_remove in
+zram_remove().
+
+This patch moves the call to idr_remove() from zram_remove() to
+hot_remove_store().  In the detroy_devices() path, idrs are removed by
+idr_destroy().  This solves an use-after-free detected by KASan.
+
+[akpm@linux-foundation.org: fix coding stype, per Sergey]
+Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
+Acked-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Cc: Minchan Kim <minchan@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/zram/zram_drv.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -1325,7 +1325,6 @@ static int zram_remove(struct zram *zram
+       pr_info("Removed device: %s\n", zram->disk->disk_name);
+-      idr_remove(&zram_index_idr, zram->disk->first_minor);
+       blk_cleanup_queue(zram->disk->queue);
+       del_gendisk(zram->disk);
+       put_disk(zram->disk);
+@@ -1367,10 +1366,12 @@ static ssize_t hot_remove_store(struct c
+       mutex_lock(&zram_index_mutex);
+       zram = idr_find(&zram_index_idr, dev_id);
+-      if (zram)
++      if (zram) {
+               ret = zram_remove(zram);
+-      else
++              idr_remove(&zram_index_idr, dev_id);
++      } else {
+               ret = -ENODEV;
++      }
+       mutex_unlock(&zram_index_mutex);
+       return ret ? ret : count;
diff --git a/queue-4.4/zram-try-vmalloc-after-kmalloc.patch b/queue-4.4/zram-try-vmalloc-after-kmalloc.patch
new file mode 100644 (file)
index 0000000..bcfb8c6
--- /dev/null
@@ -0,0 +1,155 @@
+From d913897abace843bba20249f3190167f7895e9c3 Mon Sep 17 00:00:00 2001
+From: Kyeongdon Kim <kyeongdon.kim@lge.com>
+Date: Thu, 14 Jan 2016 15:22:29 -0800
+Subject: zram: try vmalloc() after kmalloc()
+
+From: Kyeongdon Kim <kyeongdon.kim@lge.com>
+
+commit d913897abace843bba20249f3190167f7895e9c3 upstream.
+
+When we're using LZ4 multi compression streams for zram swap, we found
+out page allocation failure message in system running test.  That was
+not only once, but a few(2 - 5 times per test).  Also, some failure
+cases were continually occurring to try allocation order 3.
+
+In order to make parallel compression private data, we should call
+kzalloc() with order 2/3 in runtime(lzo/lz4).  But if there is no order
+2/3 size memory to allocate in that time, page allocation fails.  This
+patch makes to use vmalloc() as fallback of kmalloc(), this prevents
+page alloc failure warning.
+
+After using this, we never found warning message in running test, also
+It could reduce process startup latency about 60-120ms in each case.
+
+For reference a call trace :
+
+    Binder_1: page allocation failure: order:3, mode:0x10c0d0
+    CPU: 0 PID: 424 Comm: Binder_1 Tainted: GW 3.10.49-perf-g991d02b-dirty #20
+    Call trace:
+      dump_backtrace+0x0/0x270
+      show_stack+0x10/0x1c
+      dump_stack+0x1c/0x28
+      warn_alloc_failed+0xfc/0x11c
+      __alloc_pages_nodemask+0x724/0x7f0
+      __get_free_pages+0x14/0x5c
+      kmalloc_order_trace+0x38/0xd8
+      zcomp_lz4_create+0x2c/0x38
+      zcomp_strm_alloc+0x34/0x78
+      zcomp_strm_multi_find+0x124/0x1ec
+      zcomp_strm_find+0xc/0x18
+      zram_bvec_rw+0x2fc/0x780
+      zram_make_request+0x25c/0x2d4
+      generic_make_request+0x80/0xbc
+      submit_bio+0xa4/0x15c
+      __swap_writepage+0x218/0x230
+      swap_writepage+0x3c/0x4c
+      shrink_page_list+0x51c/0x8d0
+      shrink_inactive_list+0x3f8/0x60c
+      shrink_lruvec+0x33c/0x4cc
+      shrink_zone+0x3c/0x100
+      try_to_free_pages+0x2b8/0x54c
+      __alloc_pages_nodemask+0x514/0x7f0
+      __get_free_pages+0x14/0x5c
+      proc_info_read+0x50/0xe4
+      vfs_read+0xa0/0x12c
+      SyS_read+0x44/0x74
+    DMA: 3397*4kB (MC) 26*8kB (RC) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB
+         0*512kB 0*1024kB 0*2048kB 0*4096kB = 13796kB
+
+[minchan@kernel.org: change vmalloc gfp and adding comment about gfp]
+[sergey.senozhatsky@gmail.com: tweak comments and styles]
+Signed-off-by: Kyeongdon Kim <kyeongdon.kim@lge.com>
+Signed-off-by: Minchan Kim <minchan@kernel.org>
+Acked-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/zram/zcomp_lz4.c |   23 +++++++++++++++++++++--
+ drivers/block/zram/zcomp_lzo.c |   23 +++++++++++++++++++++--
+ 2 files changed, 42 insertions(+), 4 deletions(-)
+
+--- a/drivers/block/zram/zcomp_lz4.c
++++ b/drivers/block/zram/zcomp_lz4.c
+@@ -10,17 +10,36 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/lz4.h>
++#include <linux/vmalloc.h>
++#include <linux/mm.h>
+ #include "zcomp_lz4.h"
+ static void *zcomp_lz4_create(void)
+ {
+-      return kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO);
++      void *ret;
++
++      /*
++       * This function can be called in swapout/fs write path
++       * so we can't use GFP_FS|IO. And it assumes we already
++       * have at least one stream in zram initialization so we
++       * don't do best effort to allocate more stream in here.
++       * A default stream will work well without further multiple
++       * streams. That's why we use NORETRY | NOWARN.
++       */
++      ret = kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
++                                      __GFP_NOWARN);
++      if (!ret)
++              ret = __vmalloc(LZ4_MEM_COMPRESS,
++                              GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
++                              __GFP_ZERO | __GFP_HIGHMEM,
++                              PAGE_KERNEL);
++      return ret;
+ }
+ static void zcomp_lz4_destroy(void *private)
+ {
+-      kfree(private);
++      kvfree(private);
+ }
+ static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,
+--- a/drivers/block/zram/zcomp_lzo.c
++++ b/drivers/block/zram/zcomp_lzo.c
+@@ -10,17 +10,36 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/lzo.h>
++#include <linux/vmalloc.h>
++#include <linux/mm.h>
+ #include "zcomp_lzo.h"
+ static void *lzo_create(void)
+ {
+-      return kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO);
++      void *ret;
++
++      /*
++       * This function can be called in swapout/fs write path
++       * so we can't use GFP_FS|IO. And it assumes we already
++       * have at least one stream in zram initialization so we
++       * don't do best effort to allocate more stream in here.
++       * A default stream will work well without further multiple
++       * streams. That's why we use NORETRY | NOWARN.
++       */
++      ret = kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
++                                      __GFP_NOWARN);
++      if (!ret)
++              ret = __vmalloc(LZO1X_MEM_COMPRESS,
++                              GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
++                              __GFP_ZERO | __GFP_HIGHMEM,
++                              PAGE_KERNEL);
++      return ret;
+ }
+ static void lzo_destroy(void *private)
+ {
+-      kfree(private);
++      kvfree(private);
+ }
+ static int lzo_compress(const unsigned char *src, unsigned char *dst,
diff --git a/queue-4.4/zram-zcomp-use-gfp_noio-to-allocate-streams.patch b/queue-4.4/zram-zcomp-use-gfp_noio-to-allocate-streams.patch
new file mode 100644 (file)
index 0000000..c9d5bdd
--- /dev/null
@@ -0,0 +1,150 @@
+From 3d5fe03a3ea013060ebba2a811aeb0f23f56aefa Mon Sep 17 00:00:00 2001
+From: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Date: Thu, 14 Jan 2016 15:22:26 -0800
+Subject: zram/zcomp: use GFP_NOIO to allocate streams
+
+From: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+
+commit 3d5fe03a3ea013060ebba2a811aeb0f23f56aefa upstream.
+
+We can end up allocating a new compression stream with GFP_KERNEL from
+within the IO path, which may result is nested (recursive) IO
+operations.  That can introduce problems if the IO path in question is a
+reclaimer, holding some locks that will deadlock nested IOs.
+
+Allocate streams and working memory using GFP_NOIO flag, forbidding
+recursive IO and FS operations.
+
+An example:
+
+  inconsistent {IN-RECLAIM_FS-W} -> {RECLAIM_FS-ON-W} usage.
+  git/20158 [HC0[0]:SC0[0]:HE1:SE1] takes:
+   (jbd2_handle){+.+.?.}, at:  start_this_handle+0x4ca/0x555
+  {IN-RECLAIM_FS-W} state was registered at:
+     __lock_acquire+0x8da/0x117b
+     lock_acquire+0x10c/0x1a7
+     start_this_handle+0x52d/0x555
+     jbd2__journal_start+0xb4/0x237
+     __ext4_journal_start_sb+0x108/0x17e
+     ext4_dirty_inode+0x32/0x61
+     __mark_inode_dirty+0x16b/0x60c
+     iput+0x11e/0x274
+     __dentry_kill+0x148/0x1b8
+     shrink_dentry_list+0x274/0x44a
+     prune_dcache_sb+0x4a/0x55
+     super_cache_scan+0xfc/0x176
+     shrink_slab.part.14.constprop.25+0x2a2/0x4d3
+     shrink_zone+0x74/0x140
+     kswapd+0x6b7/0x930
+     kthread+0x107/0x10f
+     ret_from_fork+0x3f/0x70
+  irq event stamp: 138297
+  hardirqs last  enabled at (138297):  debug_check_no_locks_freed+0x113/0x12f
+  hardirqs last disabled at (138296):  debug_check_no_locks_freed+0x33/0x12f
+  softirqs last  enabled at (137818):  __do_softirq+0x2d3/0x3e9
+  softirqs last disabled at (137813):  irq_exit+0x41/0x95
+
+               other info that might help us debug this:
+   Possible unsafe locking scenario:
+         CPU0
+         ----
+    lock(jbd2_handle);
+    <Interrupt>
+      lock(jbd2_handle);
+
+                *** DEADLOCK ***
+  5 locks held by git/20158:
+   #0:  (sb_writers#7){.+.+.+}, at: [<ffffffff81155411>] mnt_want_write+0x24/0x4b
+   #1:  (&type->i_mutex_dir_key#2/1){+.+.+.}, at: [<ffffffff81145087>] lock_rename+0xd9/0xe3
+   #2:  (&sb->s_type->i_mutex_key#11){+.+.+.}, at: [<ffffffff8114f8e2>] lock_two_nondirectories+0x3f/0x6b
+   #3:  (&sb->s_type->i_mutex_key#11/4){+.+.+.}, at: [<ffffffff8114f909>] lock_two_nondirectories+0x66/0x6b
+   #4:  (jbd2_handle){+.+.?.}, at: [<ffffffff811e31db>] start_this_handle+0x4ca/0x555
+
+               stack backtrace:
+  CPU: 2 PID: 20158 Comm: git Not tainted 4.1.0-rc7-next-20150615-dbg-00016-g8bdf555-dirty #211
+  Call Trace:
+    dump_stack+0x4c/0x6e
+    mark_lock+0x384/0x56d
+    mark_held_locks+0x5f/0x76
+    lockdep_trace_alloc+0xb2/0xb5
+    kmem_cache_alloc_trace+0x32/0x1e2
+    zcomp_strm_alloc+0x25/0x73 [zram]
+    zcomp_strm_multi_find+0xe7/0x173 [zram]
+    zcomp_strm_find+0xc/0xe [zram]
+    zram_bvec_rw+0x2ca/0x7e0 [zram]
+    zram_make_request+0x1fa/0x301 [zram]
+    generic_make_request+0x9c/0xdb
+    submit_bio+0xf7/0x120
+    ext4_io_submit+0x2e/0x43
+    ext4_bio_write_page+0x1b7/0x300
+    mpage_submit_page+0x60/0x77
+    mpage_map_and_submit_buffers+0x10f/0x21d
+    ext4_writepages+0xc8c/0xe1b
+    do_writepages+0x23/0x2c
+    __filemap_fdatawrite_range+0x84/0x8b
+    filemap_flush+0x1c/0x1e
+    ext4_alloc_da_blocks+0xb8/0x117
+    ext4_rename+0x132/0x6dc
+    ? mark_held_locks+0x5f/0x76
+    ext4_rename2+0x29/0x2b
+    vfs_rename+0x540/0x636
+    SyS_renameat2+0x359/0x44d
+    SyS_rename+0x1e/0x20
+    entry_SYSCALL_64_fastpath+0x12/0x6f
+
+[minchan@kernel.org: add stable mark]
+Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Acked-by: Minchan Kim <minchan@kernel.org>
+Cc: Kyeongdon Kim <kyeongdon.kim@lge.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/zram/zcomp.c     |    4 ++--
+ drivers/block/zram/zcomp_lz4.c |    2 +-
+ drivers/block/zram/zcomp_lzo.c |    2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/block/zram/zcomp.c
++++ b/drivers/block/zram/zcomp.c
+@@ -76,7 +76,7 @@ static void zcomp_strm_free(struct zcomp
+  */
+ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
+ {
+-      struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
++      struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_NOIO);
+       if (!zstrm)
+               return NULL;
+@@ -85,7 +85,7 @@ static struct zcomp_strm *zcomp_strm_all
+        * allocate 2 pages. 1 for compressed data, plus 1 extra for the
+        * case when compressed size is larger than the original one
+        */
+-      zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
++      zstrm->buffer = (void *)__get_free_pages(GFP_NOIO | __GFP_ZERO, 1);
+       if (!zstrm->private || !zstrm->buffer) {
+               zcomp_strm_free(comp, zstrm);
+               zstrm = NULL;
+--- a/drivers/block/zram/zcomp_lz4.c
++++ b/drivers/block/zram/zcomp_lz4.c
+@@ -15,7 +15,7 @@
+ static void *zcomp_lz4_create(void)
+ {
+-      return kzalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
++      return kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO);
+ }
+ static void zcomp_lz4_destroy(void *private)
+--- a/drivers/block/zram/zcomp_lzo.c
++++ b/drivers/block/zram/zcomp_lzo.c
+@@ -15,7 +15,7 @@
+ static void *lzo_create(void)
+ {
+-      return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
++      return kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO);
+ }
+ static void lzo_destroy(void *private)
diff --git a/queue-4.4/zsmalloc-fix-migrate_zspage-zs_free-race-condition.patch b/queue-4.4/zsmalloc-fix-migrate_zspage-zs_free-race-condition.patch
new file mode 100644 (file)
index 0000000..f18ddd2
--- /dev/null
@@ -0,0 +1,96 @@
+From c102f07ca0b04f2cb49cfc161c83f6239d17f491 Mon Sep 17 00:00:00 2001
+From: Junil Lee <junil0814.lee@lge.com>
+Date: Wed, 20 Jan 2016 14:58:18 -0800
+Subject: zsmalloc: fix migrate_zspage-zs_free race condition
+
+From: Junil Lee <junil0814.lee@lge.com>
+
+commit c102f07ca0b04f2cb49cfc161c83f6239d17f491 upstream.
+
+record_obj() in migrate_zspage() does not preserve handle's
+HANDLE_PIN_BIT, set by find_aloced_obj()->trypin_tag(), and implicitly
+(accidentally) un-pins the handle, while migrate_zspage() still performs
+an explicit unpin_tag() on the that handle.  This additional explicit
+unpin_tag() introduces a race condition with zs_free(), which can pin
+that handle by this time, so the handle becomes un-pinned.
+
+Schematically, it goes like this:
+
+  CPU0                                        CPU1
+  migrate_zspage
+    find_alloced_obj
+      trypin_tag
+        set HANDLE_PIN_BIT                    zs_free()
+                                                pin_tag()
+  obj_malloc() -- new object, no tag
+  record_obj() -- remove HANDLE_PIN_BIT           set HANDLE_PIN_BIT
+  unpin_tag()  -- remove zs_free's HANDLE_PIN_BIT
+
+The race condition may result in a NULL pointer dereference:
+
+  Unable to handle kernel NULL pointer dereference at virtual address 00000000
+  CPU: 0 PID: 19001 Comm: CookieMonsterCl Tainted:
+  PC is at get_zspage_mapping+0x0/0x24
+  LR is at obj_free.isra.22+0x64/0x128
+  Call trace:
+     get_zspage_mapping+0x0/0x24
+     zs_free+0x88/0x114
+     zram_free_page+0x64/0xcc
+     zram_slot_free_notify+0x90/0x108
+     swap_entry_free+0x278/0x294
+     free_swap_and_cache+0x38/0x11c
+     unmap_single_vma+0x480/0x5c8
+     unmap_vmas+0x44/0x60
+     exit_mmap+0x50/0x110
+     mmput+0x58/0xe0
+     do_exit+0x320/0x8dc
+     do_group_exit+0x44/0xa8
+     get_signal+0x538/0x580
+     do_signal+0x98/0x4b8
+     do_notify_resume+0x14/0x5c
+
+This patch keeps the lock bit in migration path and update value
+atomically.
+
+Signed-off-by: Junil Lee <junil0814.lee@lge.com>
+Signed-off-by: Minchan Kim <minchan@kernel.org>
+Acked-by: Vlastimil Babka <vbabka@suse.cz>
+Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/zsmalloc.c |   14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/mm/zsmalloc.c
++++ b/mm/zsmalloc.c
+@@ -309,7 +309,12 @@ static void free_handle(struct zs_pool *
+ static void record_obj(unsigned long handle, unsigned long obj)
+ {
+-      *(unsigned long *)handle = obj;
++      /*
++       * lsb of @obj represents handle lock while other bits
++       * represent object value the handle is pointing so
++       * updating shouldn't do store tearing.
++       */
++      WRITE_ONCE(*(unsigned long *)handle, obj);
+ }
+ /* zpool driver */
+@@ -1635,6 +1640,13 @@ static int migrate_zspage(struct zs_pool
+               free_obj = obj_malloc(d_page, class, handle);
+               zs_object_copy(free_obj, used_obj, class);
+               index++;
++              /*
++               * record_obj updates handle's value to free_obj and it will
++               * invalidate lock bit(ie, HANDLE_PIN_BIT) of handle, which
++               * breaks synchronization using pin_tag(e,g, zs_free) so
++               * let's keep the lock bit.
++               */
++              free_obj |= BIT(HANDLE_PIN_BIT);
+               record_obj(handle, free_obj);
+               unpin_tag(handle);
+               obj_free(pool, class, used_obj);