]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.3-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 22:18:20 +0000 (14:18 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 22:18:20 +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-marvell-cesa-fix-test-in-mv_cesa_dev_dma_init.patch
crypto-user-lock-crypto_alg_list-on-alg-dump.patch
drm-nouveau-pmu-do-not-assume-a-pmu-is-present.patch
evm-use-crypto_memneq-for-digest-comparisons.patch
fs-cache-add-missing-initialization-of-ret-in-cachefiles_write_page.patch
fs-cache-don-t-override-netfs-s-primary_index-if-registering-failed.patch
fs-cache-handle-a-write-to-the-page-immediately-beyond-the-eof-marker.patch
fs-cache-increase-reference-of-parent-after-registering-netfs-success.patch
hid-multitouch-fetch-feature-reports-on-demand-for-win8-devices.patch
rtlwifi-rtl8821ae-fix-lockups-on-boot.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

19 files changed:
queue-4.3/crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch [new file with mode: 0644]
queue-4.3/crypto-algif_skcipher-do-not-assume-that-req-is-unchanged.patch [new file with mode: 0644]
queue-4.3/crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch [new file with mode: 0644]
queue-4.3/crypto-algif_skcipher-do-not-set-may_backlog-on-the-async-path.patch [new file with mode: 0644]
queue-4.3/crypto-marvell-cesa-fix-test-in-mv_cesa_dev_dma_init.patch [new file with mode: 0644]
queue-4.3/crypto-user-lock-crypto_alg_list-on-alg-dump.patch [new file with mode: 0644]
queue-4.3/drm-nouveau-pmu-do-not-assume-a-pmu-is-present.patch [new file with mode: 0644]
queue-4.3/evm-use-crypto_memneq-for-digest-comparisons.patch [new file with mode: 0644]
queue-4.3/fs-cache-add-missing-initialization-of-ret-in-cachefiles_write_page.patch [new file with mode: 0644]
queue-4.3/fs-cache-don-t-override-netfs-s-primary_index-if-registering-failed.patch [new file with mode: 0644]
queue-4.3/fs-cache-handle-a-write-to-the-page-immediately-beyond-the-eof-marker.patch [new file with mode: 0644]
queue-4.3/fs-cache-increase-reference-of-parent-after-registering-netfs-success.patch [new file with mode: 0644]
queue-4.3/hid-multitouch-fetch-feature-reports-on-demand-for-win8-devices.patch [new file with mode: 0644]
queue-4.3/rtlwifi-rtl8821ae-fix-lockups-on-boot.patch [new file with mode: 0644]
queue-4.3/series
queue-4.3/zram-don-t-call-idr_remove-from-zram_remove.patch [new file with mode: 0644]
queue-4.3/zram-try-vmalloc-after-kmalloc.patch [new file with mode: 0644]
queue-4.3/zram-zcomp-use-gfp_noio-to-allocate-streams.patch [new file with mode: 0644]
queue-4.3/zsmalloc-fix-migrate_zspage-zs_free-race-condition.patch [new file with mode: 0644]

diff --git a/queue-4.3/crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch b/queue-4.3/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.3/crypto-algif_skcipher-do-not-assume-that-req-is-unchanged.patch b/queue-4.3/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.3/crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch b/queue-4.3/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.3/crypto-algif_skcipher-do-not-set-may_backlog-on-the-async-path.patch b/queue-4.3/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.3/crypto-marvell-cesa-fix-test-in-mv_cesa_dev_dma_init.patch b/queue-4.3/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.3/crypto-user-lock-crypto_alg_list-on-alg-dump.patch b/queue-4.3/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.3/drm-nouveau-pmu-do-not-assume-a-pmu-is-present.patch b/queue-4.3/drm-nouveau-pmu-do-not-assume-a-pmu-is-present.patch
new file mode 100644 (file)
index 0000000..244fa09
--- /dev/null
@@ -0,0 +1,32 @@
+From 579b7c58215329803ce184704463de09f0f310ac Mon Sep 17 00:00:00 2001
+From: Alexandre Courbot <acourbot@nvidia.com>
+Date: Thu, 3 Sep 2015 17:39:52 +0900
+Subject: drm/nouveau/pmu: do not assume a PMU is present
+
+From: Alexandre Courbot <acourbot@nvidia.com>
+
+commit 579b7c58215329803ce184704463de09f0f310ac upstream.
+
+Some devices may not have a PMU. Avoid a NULL pointer dereference in
+such cases by checking whether the pointer given to nvkm_pmu_pgob() is
+valid.
+
+Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
+Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
+@@ -28,7 +28,7 @@
+ void
+ nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable)
+ {
+-      if (pmu->func->pgob)
++      if (pmu && pmu->func->pgob)
+               pmu->func->pgob(pmu, enable);
+ }
diff --git a/queue-4.3/evm-use-crypto_memneq-for-digest-comparisons.patch b/queue-4.3/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.3/fs-cache-add-missing-initialization-of-ret-in-cachefiles_write_page.patch b/queue-4.3/fs-cache-add-missing-initialization-of-ret-in-cachefiles_write_page.patch
new file mode 100644 (file)
index 0000000..54e0e50
--- /dev/null
@@ -0,0 +1,40 @@
+From cf89752645e47d86ba8a4157f4b121fcb33434c5 Mon Sep 17 00:00:00 2001
+From: Geert Uytterhoeven <geert@linux-m68k.org>
+Date: Thu, 12 Nov 2015 11:46:23 +0000
+Subject: FS-Cache: Add missing initialization of ret in cachefiles_write_page()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Geert Uytterhoeven <geert@linux-m68k.org>
+
+commit cf89752645e47d86ba8a4157f4b121fcb33434c5 upstream.
+
+fs/cachefiles/rdwr.c: In function â€˜cachefiles_write_page’:
+fs/cachefiles/rdwr.c:882: warning: â€˜ret’ may be used uninitialized in
+this function
+
+If the jump to label "error" is taken, "ret" will indeed be
+uninitialized, and random stack data may be printed by the debug code.
+
+Fixes: 102f4d900c9c8f5e ("FS-Cache: Handle a write to the page immediately beyond the EOF marker")
+Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cachefiles/rdwr.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/cachefiles/rdwr.c
++++ b/fs/cachefiles/rdwr.c
+@@ -885,7 +885,7 @@ int cachefiles_write_page(struct fscache
+       loff_t pos, eof;
+       size_t len;
+       void *data;
+-      int ret;
++      int ret = -ENOBUFS;
+       ASSERT(op != NULL);
+       ASSERT(page != NULL);
diff --git a/queue-4.3/fs-cache-don-t-override-netfs-s-primary_index-if-registering-failed.patch b/queue-4.3/fs-cache-don-t-override-netfs-s-primary_index-if-registering-failed.patch
new file mode 100644 (file)
index 0000000..de820e4
--- /dev/null
@@ -0,0 +1,95 @@
+From b130ed5998e62879a66bad08931a2b5e832da95c Mon Sep 17 00:00:00 2001
+From: Kinglong Mee <kinglongmee@gmail.com>
+Date: Wed, 4 Nov 2015 15:20:24 +0000
+Subject: FS-Cache: Don't override netfs's primary_index if registering failed
+
+From: Kinglong Mee <kinglongmee@gmail.com>
+
+commit b130ed5998e62879a66bad08931a2b5e832da95c upstream.
+
+Only override netfs->primary_index when registering success.
+
+Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/fscache/netfs.c |   37 ++++++++++++++++++-------------------
+ 1 file changed, 18 insertions(+), 19 deletions(-)
+
+--- a/fs/fscache/netfs.c
++++ b/fs/fscache/netfs.c
+@@ -22,6 +22,7 @@ static LIST_HEAD(fscache_netfs_list);
+ int __fscache_register_netfs(struct fscache_netfs *netfs)
+ {
+       struct fscache_netfs *ptr;
++      struct fscache_cookie *cookie;
+       int ret;
+       _enter("{%s}", netfs->name);
+@@ -29,26 +30,25 @@ int __fscache_register_netfs(struct fsca
+       INIT_LIST_HEAD(&netfs->link);
+       /* allocate a cookie for the primary index */
+-      netfs->primary_index =
+-              kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL);
++      cookie = kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL);
+-      if (!netfs->primary_index) {
++      if (!cookie) {
+               _leave(" = -ENOMEM");
+               return -ENOMEM;
+       }
+       /* initialise the primary index cookie */
+-      atomic_set(&netfs->primary_index->usage, 1);
+-      atomic_set(&netfs->primary_index->n_children, 0);
+-      atomic_set(&netfs->primary_index->n_active, 1);
+-
+-      netfs->primary_index->def               = &fscache_fsdef_netfs_def;
+-      netfs->primary_index->parent            = &fscache_fsdef_index;
+-      netfs->primary_index->netfs_data        = netfs;
+-      netfs->primary_index->flags             = 1 << FSCACHE_COOKIE_ENABLED;
++      atomic_set(&cookie->usage, 1);
++      atomic_set(&cookie->n_children, 0);
++      atomic_set(&cookie->n_active, 1);
++
++      cookie->def             = &fscache_fsdef_netfs_def;
++      cookie->parent          = &fscache_fsdef_index;
++      cookie->netfs_data      = netfs;
++      cookie->flags           = 1 << FSCACHE_COOKIE_ENABLED;
+-      spin_lock_init(&netfs->primary_index->lock);
+-      INIT_HLIST_HEAD(&netfs->primary_index->backing_objects);
++      spin_lock_init(&cookie->lock);
++      INIT_HLIST_HEAD(&cookie->backing_objects);
+       /* check the netfs type is not already present */
+       down_write(&fscache_addremove_sem);
+@@ -59,9 +59,10 @@ int __fscache_register_netfs(struct fsca
+                       goto already_registered;
+       }
+-      atomic_inc(&netfs->primary_index->parent->usage);
+-      atomic_inc(&netfs->primary_index->parent->n_children);
++      atomic_inc(&cookie->parent->usage);
++      atomic_inc(&cookie->parent->n_children);
++      netfs->primary_index = cookie;
+       list_add(&netfs->link, &fscache_netfs_list);
+       ret = 0;
+@@ -70,10 +71,8 @@ int __fscache_register_netfs(struct fsca
+ already_registered:
+       up_write(&fscache_addremove_sem);
+-      if (ret < 0) {
+-              kmem_cache_free(fscache_cookie_jar, netfs->primary_index);
+-              netfs->primary_index = NULL;
+-      }
++      if (ret < 0)
++              kmem_cache_free(fscache_cookie_jar, cookie);
+       _leave(" = %d", ret);
+       return ret;
diff --git a/queue-4.3/fs-cache-handle-a-write-to-the-page-immediately-beyond-the-eof-marker.patch b/queue-4.3/fs-cache-handle-a-write-to-the-page-immediately-beyond-the-eof-marker.patch
new file mode 100644 (file)
index 0000000..9a84fc1
--- /dev/null
@@ -0,0 +1,141 @@
+From 102f4d900c9c8f5ed89ae4746d493fe3ebd7ba64 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Wed, 4 Nov 2015 15:20:42 +0000
+Subject: FS-Cache: Handle a write to the page immediately beyond the EOF marker
+
+From: David Howells <dhowells@redhat.com>
+
+commit 102f4d900c9c8f5ed89ae4746d493fe3ebd7ba64 upstream.
+
+Handle a write being requested to the page immediately beyond the EOF
+marker on a cache object.  Currently this gets an assertion failure in
+CacheFiles because the EOF marker is used there to encode information about
+a partial page at the EOF - which could lead to an unknown blank spot in
+the file if we extend the file over it.
+
+The problem is actually in fscache where we check the index of the page
+being written against store_limit.  store_limit is set to the number of
+pages that we're allowed to store by fscache_set_store_limit() - which
+means it's one more than the index of the last page we're allowed to store.
+The problem is that we permit writing to a page with an index _equal_ to
+the store limit - when we should reject that case.
+
+Whilst we're at it, change the triggered assertion in CacheFiles to just
+return -ENOBUFS instead.
+
+The assertion failure looks something like this:
+
+CacheFiles: Assertion failed
+1000 < 7b1 is false
+------------[ cut here ]------------
+kernel BUG at fs/cachefiles/rdwr.c:962!
+...
+RIP: 0010:[<ffffffffa02c9e83>]  [<ffffffffa02c9e83>] cachefiles_write_page+0x273/0x2d0 [cachefiles]
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cachefiles/rdwr.c |   67 ++++++++++++++++++++++++++++-----------------------
+ fs/fscache/page.c    |    2 -
+ 2 files changed, 38 insertions(+), 31 deletions(-)
+
+--- a/fs/cachefiles/rdwr.c
++++ b/fs/cachefiles/rdwr.c
+@@ -905,6 +905,15 @@ int cachefiles_write_page(struct fscache
+       cache = container_of(object->fscache.cache,
+                            struct cachefiles_cache, cache);
++      pos = (loff_t)page->index << PAGE_SHIFT;
++
++      /* We mustn't write more data than we have, so we have to beware of a
++       * partial page at EOF.
++       */
++      eof = object->fscache.store_limit_l;
++      if (pos >= eof)
++              goto error;
++
+       /* write the page to the backing filesystem and let it store it in its
+        * own time */
+       path.mnt = cache->mnt;
+@@ -912,40 +921,38 @@ int cachefiles_write_page(struct fscache
+       file = dentry_open(&path, O_RDWR | O_LARGEFILE, cache->cache_cred);
+       if (IS_ERR(file)) {
+               ret = PTR_ERR(file);
+-      } else {
+-              pos = (loff_t) page->index << PAGE_SHIFT;
+-
+-              /* we mustn't write more data than we have, so we have
+-               * to beware of a partial page at EOF */
+-              eof = object->fscache.store_limit_l;
+-              len = PAGE_SIZE;
+-              if (eof & ~PAGE_MASK) {
+-                      ASSERTCMP(pos, <, eof);
+-                      if (eof - pos < PAGE_SIZE) {
+-                              _debug("cut short %llx to %llx",
+-                                     pos, eof);
+-                              len = eof - pos;
+-                              ASSERTCMP(pos + len, ==, eof);
+-                      }
+-              }
+-
+-              data = kmap(page);
+-              ret = __kernel_write(file, data, len, &pos);
+-              kunmap(page);
+-              if (ret != len)
+-                      ret = -EIO;
+-              fput(file);
++              goto error_2;
+       }
+-      if (ret < 0) {
+-              if (ret == -EIO)
+-                      cachefiles_io_error_obj(
+-                              object, "Write page to backing file failed");
+-              ret = -ENOBUFS;
++      len = PAGE_SIZE;
++      if (eof & ~PAGE_MASK) {
++              if (eof - pos < PAGE_SIZE) {
++                      _debug("cut short %llx to %llx",
++                             pos, eof);
++                      len = eof - pos;
++                      ASSERTCMP(pos + len, ==, eof);
++              }
+       }
+-      _leave(" = %d", ret);
+-      return ret;
++      data = kmap(page);
++      ret = __kernel_write(file, data, len, &pos);
++      kunmap(page);
++      fput(file);
++      if (ret != len)
++              goto error_eio;
++
++      _leave(" = 0");
++      return 0;
++
++error_eio:
++      ret = -EIO;
++error_2:
++      if (ret == -EIO)
++              cachefiles_io_error_obj(object,
++                                      "Write page to backing file failed");
++error:
++      _leave(" = -ENOBUFS [%d]", ret);
++      return -ENOBUFS;
+ }
+ /*
+--- a/fs/fscache/page.c
++++ b/fs/fscache/page.c
+@@ -816,7 +816,7 @@ static void fscache_write_op(struct fsca
+               goto superseded;
+       page = results[0];
+       _debug("gang %d [%lx]", n, page->index);
+-      if (page->index > op->store_limit) {
++      if (page->index >= op->store_limit) {
+               fscache_stat(&fscache_n_store_pages_over_limit);
+               goto superseded;
+       }
diff --git a/queue-4.3/fs-cache-increase-reference-of-parent-after-registering-netfs-success.patch b/queue-4.3/fs-cache-increase-reference-of-parent-after-registering-netfs-success.patch
new file mode 100644 (file)
index 0000000..865c4fa
--- /dev/null
@@ -0,0 +1,59 @@
+From 86108c2e34a26e4bec3c6ddb23390bf8cedcf391 Mon Sep 17 00:00:00 2001
+From: Kinglong Mee <kinglongmee@gmail.com>
+Date: Wed, 4 Nov 2015 15:20:15 +0000
+Subject: FS-Cache: Increase reference of parent after registering, netfs success
+
+From: Kinglong Mee <kinglongmee@gmail.com>
+
+commit 86108c2e34a26e4bec3c6ddb23390bf8cedcf391 upstream.
+
+If netfs exist, fscache should not increase the reference of parent's
+usage and n_children, otherwise, never be decreased.
+
+v2: thanks David's suggest,
+ move increasing reference of parent if success
+ use kmem_cache_free() freeing primary_index directly
+
+v3: don't move "netfs->primary_index->parent = &fscache_fsdef_index;"
+
+Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/fscache/netfs.c |    9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/fs/fscache/netfs.c
++++ b/fs/fscache/netfs.c
+@@ -47,9 +47,6 @@ int __fscache_register_netfs(struct fsca
+       netfs->primary_index->netfs_data        = netfs;
+       netfs->primary_index->flags             = 1 << FSCACHE_COOKIE_ENABLED;
+-      atomic_inc(&netfs->primary_index->parent->usage);
+-      atomic_inc(&netfs->primary_index->parent->n_children);
+-
+       spin_lock_init(&netfs->primary_index->lock);
+       INIT_HLIST_HEAD(&netfs->primary_index->backing_objects);
+@@ -62,6 +59,9 @@ int __fscache_register_netfs(struct fsca
+                       goto already_registered;
+       }
++      atomic_inc(&netfs->primary_index->parent->usage);
++      atomic_inc(&netfs->primary_index->parent->n_children);
++
+       list_add(&netfs->link, &fscache_netfs_list);
+       ret = 0;
+@@ -71,8 +71,7 @@ already_registered:
+       up_write(&fscache_addremove_sem);
+       if (ret < 0) {
+-              netfs->primary_index->parent = NULL;
+-              __fscache_cookie_put(netfs->primary_index);
++              kmem_cache_free(fscache_cookie_jar, netfs->primary_index);
+               netfs->primary_index = NULL;
+       }
diff --git a/queue-4.3/hid-multitouch-fetch-feature-reports-on-demand-for-win8-devices.patch b/queue-4.3/hid-multitouch-fetch-feature-reports-on-demand-for-win8-devices.patch
new file mode 100644 (file)
index 0000000..cade1b4
--- /dev/null
@@ -0,0 +1,133 @@
+From 6d4f5440a3a2bb2e9d0d582bbf98234e9e9bb095 Mon Sep 17 00:00:00 2001
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+Date: Wed, 7 Oct 2015 15:33:43 +0300
+Subject: HID: multitouch: Fetch feature reports on demand for Win8 devices
+
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+
+commit 6d4f5440a3a2bb2e9d0d582bbf98234e9e9bb095 upstream.
+
+Some newer Intel Skylake based Dell laptops with Win8 precision touchpad
+fail when initial feature reports are fetched from it. Below is an example
+output with some additional debug included:
+
+ i2c_hid i2c-DLL0704:01: Fetching the HID descriptor
+ i2c_hid i2c-DLL0704:01: __i2c_hid_command: cmd=20 00
+ i2c_hid i2c-DLL0704:01: HID Descriptor: 1e 00 00 01 99 02 21 00 24 ...
+ ...
+ i2c_hid i2c-DLL0704:01: i2c_hid_get_report
+ i2c_hid i2c-DLL0704:01: __i2c_hid_command: cmd=22 00 38 02 23 00
+ i2c_hid i2c-DLL0704:01: report (len=4): 04 00 08 05
+ i2c_hid i2c-DLL0704:01: report id 13
+ i2c_hid i2c-DLL0704:01: i2c_hid_get_report
+ i2c_hid i2c-DLL0704:01: __i2c_hid_command: cmd=22 00 3d 02 23 00
+ i2c_hid i2c-DLL0704:01: failed to retrieve report from device.
+ i2c_hid i2c-DLL0704:01: report id 7
+ i2c_hid i2c-DLL0704:01: i2c_hid_get_report
+ i2c_hid i2c-DLL0704:01: __i2c_hid_command: cmd=22 00 37 02 23 00
+ i2c_hid i2c-DLL0704:01: report (len=259): 03 01 07 fc 28 fe 84 40 ...
+ i2c_hid i2c-DLL0704:01: report id 4
+ i2c_hid i2c-DLL0704:01: i2c_hid_get_report
+ i2c_hid i2c-DLL0704:01: __i2c_hid_command: cmd=22 00 34 02 23 00
+
+We manage to fetch few reports but then the touchpad dies:
+
+ i2c_designware i2c_designware.1: i2c_dw_handle_tx_abort: lost arbitration
+ i2c_hid i2c-DLL0704:01: failed to retrieve report from device.
+
+it eventually pulls the whole I2C bus low:
+
+ i2c_designware i2c_designware.1: controller timed out
+ i2c_hid i2c-DLL0704:01: failed to set a report to device.
+
+Fix this by preventing initial feature report retrieval for Win8 devices.
+Instead we fetch reports as needed in mt_feature_mapping(). This prevents
+fetching reports which might cause problems with the device in question.
+
+Suggested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Tested-by: Seth Forshee <seth.forshee@canonical.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-multitouch.c |   45 ++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 44 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -309,6 +309,41 @@ static struct attribute_group mt_attribu
+       .attrs = sysfs_attrs
+ };
++static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
++{
++      struct mt_device *td = hid_get_drvdata(hdev);
++      int ret, size = hid_report_len(report);
++      u8 *buf;
++
++      /*
++       * Only fetch the feature report if initial reports are not already
++       * been retrieved. Currently this is only done for Windows 8 touch
++       * devices.
++       */
++      if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS))
++              return;
++      if (td->mtclass.name != MT_CLS_WIN_8)
++              return;
++
++      buf = hid_alloc_report_buf(report, GFP_KERNEL);
++      if (!buf)
++              return;
++
++      ret = hid_hw_raw_request(hdev, report->id, buf, size,
++                               HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
++      if (ret < 0) {
++              dev_warn(&hdev->dev, "failed to fetch feature %d\n",
++                       report->id);
++      } else {
++              ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
++                                         size, 0);
++              if (ret)
++                      dev_warn(&hdev->dev, "failed to report feature\n");
++      }
++
++      kfree(buf);
++}
++
+ static void mt_feature_mapping(struct hid_device *hdev,
+               struct hid_field *field, struct hid_usage *usage)
+ {
+@@ -327,6 +362,8 @@ static void mt_feature_mapping(struct hi
+               break;
+       case HID_DG_CONTACTMAX:
++              mt_get_feature(hdev, field->report);
++
+               td->maxcontact_report_id = field->report->id;
+               td->maxcontacts = field->value[0];
+               if (!td->maxcontacts &&
+@@ -343,6 +380,7 @@ static void mt_feature_mapping(struct hi
+                       break;
+               }
++              mt_get_feature(hdev, field->report);
+               if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
+                       td->is_buttonpad = true;
+@@ -1026,8 +1064,13 @@ static int mt_probe(struct hid_device *h
+                * reports. Fortunately, the Win8 spec says that all touches
+                * should be sent during each report, making the initialization
+                * of input reports unnecessary.
++               *
++               * In addition some touchpads do not behave well if we read
++               * all feature reports from them. Instead we prevent
++               * initial report fetching and then selectively fetch each
++               * report we are interested in.
+                */
+-              hdev->quirks |= HID_QUIRK_NO_INIT_INPUT_REPORTS;
++              hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
+       td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
+       if (!td) {
diff --git a/queue-4.3/rtlwifi-rtl8821ae-fix-lockups-on-boot.patch b/queue-4.3/rtlwifi-rtl8821ae-fix-lockups-on-boot.patch
new file mode 100644 (file)
index 0000000..ad30156
--- /dev/null
@@ -0,0 +1,51 @@
+From eeec5d0ef7ee54a75e09e861c3cc44177b8752c7 Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Tue, 10 Nov 2015 10:46:11 -0600
+Subject: rtlwifi: rtl8821ae: Fix lockups on boot
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit eeec5d0ef7ee54a75e09e861c3cc44177b8752c7 upstream.
+
+In commit 54328e64047a5 ("rtlwifi: rtl8821ae: Fix system lockups on boot"),
+an attempt was made to fix a regression introduced in commit 1277fa2ab2f9
+("rtlwifi: Remove the clear interrupt routine from all drivers").
+Unfortunately, there were logic errors in that patch that prevented
+affected boxes from booting even after that patch was applied.
+
+The actual cause of the original problem is unknown as none of the
+developers have systems that are affected.
+
+Fixes: 54328e64047a ("rtlwifi: rtl8821ae: Fix system lockups on boot")
+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/rtlwifi/rtl8821ae/hw.c |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8821ae/sw.c |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
+@@ -2272,7 +2272,7 @@ void rtl8821ae_enable_interrupt(struct i
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+-      if (!rtlpci->int_clear)
++      if (rtlpci->int_clear)
+               rtl8821ae_clear_interrupt(hw);/*clear it here first*/
+       rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
+--- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
+@@ -448,7 +448,7 @@ MODULE_PARM_DESC(fwlps, "Set to 1 to use
+ MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n");
+ MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+ MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n");
+-MODULE_PARM_DESC(int_clear, "Set to 1 to disable interrupt clear before set (default 0)\n");
++MODULE_PARM_DESC(int_clear, "Set to 0 to disable interrupt clear before set (default 1)\n");
+ static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
index a35c096df5315fd7c4403be60464c9c3c7fa3b87..229d2196a4607d69f11409be5c93da70fca2d913 100644 (file)
@@ -178,3 +178,21 @@ 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-marvell-cesa-fix-test-in-mv_cesa_dev_dma_init.patch
+fs-cache-increase-reference-of-parent-after-registering-netfs-success.patch
+fs-cache-don-t-override-netfs-s-primary_index-if-registering-failed.patch
+fs-cache-handle-a-write-to-the-page-immediately-beyond-the-eof-marker.patch
+fs-cache-add-missing-initialization-of-ret-in-cachefiles_write_page.patch
+rtlwifi-rtl8821ae-fix-lockups-on-boot.patch
+hid-multitouch-fetch-feature-reports-on-demand-for-win8-devices.patch
+drm-nouveau-pmu-do-not-assume-a-pmu-is-present.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.3/zram-don-t-call-idr_remove-from-zram_remove.patch b/queue-4.3/zram-don-t-call-idr_remove-from-zram_remove.patch
new file mode 100644 (file)
index 0000000..a0c97fc
--- /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
+@@ -1324,7 +1324,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);
+@@ -1366,10 +1365,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.3/zram-try-vmalloc-after-kmalloc.patch b/queue-4.3/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.3/zram-zcomp-use-gfp_noio-to-allocate-streams.patch b/queue-4.3/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.3/zsmalloc-fix-migrate_zspage-zs_free-race-condition.patch b/queue-4.3/zsmalloc-fix-migrate_zspage-zs_free-race-condition.patch
new file mode 100644 (file)
index 0000000..2bb3977
--- /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
+@@ -304,7 +304,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 */
+@@ -1629,6 +1634,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);