]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Feb 2015 23:06:06 +0000 (15:06 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Feb 2015 23:06:06 +0000 (15:06 -0800)
added patches:
added-little-endian-support-to-vtpm-module.patch
cfq-iosched-fix-incorrect-filing-of-rt-async-cfqq.patch
cfq-iosched-handle-failure-of-cfq-group-allocation.patch
char-tpm-add-missing-error-check-for-devm_kzalloc.patch
cipso-don-t-use-ipcb-to-locate-the-cipso-ip-option.patch
iscsi-target-drop-problematic-active_ts_list-usage.patch
nfs41-.init_read-and-.init_write-can-be-called-with-valid-pg_lseg.patch
nfsv4-ensure-we-reference-the-inode-for-return-on-close-in-delegreturn.patch
nfsv4.1-fix-a-kfree-of-uninitialised-pointers-in-decode_cb_sequence_args.patch
sg-fix-ewouldblock-errors-with-scsi-mq.patch
sg-fix-unkillable-i-o-wait-deadlock-with-scsi-mq.patch
sunrpc-null-utsname-dereference-on-nfs-umount-during-namespace-cleanup.patch
tpm-add-new-tpms-to-the-tail-of-the-list-to-prevent-inadvertent-change-of-dev.patch
tpm-fix-null-return-in-tpm_ibmvtpm_get_desired_dma.patch
tpm-tpm_i2c_stm_st33-fix-potential-bug-in-tpm_stm_i2c_send.patch

16 files changed:
queue-3.19/added-little-endian-support-to-vtpm-module.patch [new file with mode: 0644]
queue-3.19/cfq-iosched-fix-incorrect-filing-of-rt-async-cfqq.patch [new file with mode: 0644]
queue-3.19/cfq-iosched-handle-failure-of-cfq-group-allocation.patch [new file with mode: 0644]
queue-3.19/char-tpm-add-missing-error-check-for-devm_kzalloc.patch [new file with mode: 0644]
queue-3.19/cipso-don-t-use-ipcb-to-locate-the-cipso-ip-option.patch [new file with mode: 0644]
queue-3.19/iscsi-target-drop-problematic-active_ts_list-usage.patch [new file with mode: 0644]
queue-3.19/nfs41-.init_read-and-.init_write-can-be-called-with-valid-pg_lseg.patch [new file with mode: 0644]
queue-3.19/nfsv4-ensure-we-reference-the-inode-for-return-on-close-in-delegreturn.patch [new file with mode: 0644]
queue-3.19/nfsv4.1-fix-a-kfree-of-uninitialised-pointers-in-decode_cb_sequence_args.patch [new file with mode: 0644]
queue-3.19/series
queue-3.19/sg-fix-ewouldblock-errors-with-scsi-mq.patch [new file with mode: 0644]
queue-3.19/sg-fix-unkillable-i-o-wait-deadlock-with-scsi-mq.patch [new file with mode: 0644]
queue-3.19/sunrpc-null-utsname-dereference-on-nfs-umount-during-namespace-cleanup.patch [new file with mode: 0644]
queue-3.19/tpm-add-new-tpms-to-the-tail-of-the-list-to-prevent-inadvertent-change-of-dev.patch [new file with mode: 0644]
queue-3.19/tpm-fix-null-return-in-tpm_ibmvtpm_get_desired_dma.patch [new file with mode: 0644]
queue-3.19/tpm-tpm_i2c_stm_st33-fix-potential-bug-in-tpm_stm_i2c_send.patch [new file with mode: 0644]

diff --git a/queue-3.19/added-little-endian-support-to-vtpm-module.patch b/queue-3.19/added-little-endian-support-to-vtpm-module.patch
new file mode 100644 (file)
index 0000000..d117636
--- /dev/null
@@ -0,0 +1,100 @@
+From eb71f8a5e33fa1066fb92f0111ab366a341e1f6c Mon Sep 17 00:00:00 2001
+From: honclo <honclo@imap.linux.ibm.com>
+Date: Thu, 12 Feb 2015 21:02:24 -0500
+Subject: Added Little Endian support to vtpm module
+
+From: honclo <honclo@imap.linux.ibm.com>
+
+commit eb71f8a5e33fa1066fb92f0111ab366a341e1f6c upstream.
+
+The tpm_ibmvtpm module is affected by an unaligned access problem.
+ibmvtpm_crq_get_version failed with rc=-4 during boot when vTPM is
+enabled in Power partition, which supports both little endian and
+big endian modes.
+
+We added little endian support to fix this problem:
+1) added cpu_to_be64 calls to ensure BE data is sent from an LE OS.
+2) added be16_to_cpu and be32_to_cpu calls to make sure data received
+   is in LE format on a LE OS.
+
+Signed-off-by: Hon Ching(Vicky) Lo <honclo@linux.vnet.ibm.com>
+Signed-off-by: Joy Latten <jmlatten@linux.vnet.ibm.com>
+[phuewe: manually applied the patch :( ]
+Reviewed-by: Ashley Lai <ashley@ahsleylai.com>
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_ibmvtpm.c |   20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+--- a/drivers/char/tpm/tpm_ibmvtpm.c
++++ b/drivers/char/tpm/tpm_ibmvtpm.c
+@@ -148,7 +148,8 @@ static int tpm_ibmvtpm_send(struct tpm_c
+       crq.len = (u16)count;
+       crq.data = ibmvtpm->rtce_dma_handle;
+-      rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]);
++      rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]),
++                            cpu_to_be64(word[1]));
+       if (rc != H_SUCCESS) {
+               dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
+               rc = 0;
+@@ -186,7 +187,8 @@ static int ibmvtpm_crq_get_rtce_size(str
+       crq.valid = (u8)IBMVTPM_VALID_CMD;
+       crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
+-      rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
++      rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
++                            cpu_to_be64(buf[1]));
+       if (rc != H_SUCCESS)
+               dev_err(ibmvtpm->dev,
+                       "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
+@@ -212,7 +214,8 @@ static int ibmvtpm_crq_get_version(struc
+       crq.valid = (u8)IBMVTPM_VALID_CMD;
+       crq.msg = (u8)VTPM_GET_VERSION;
+-      rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
++      rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
++                            cpu_to_be64(buf[1]));
+       if (rc != H_SUCCESS)
+               dev_err(ibmvtpm->dev,
+                       "ibmvtpm_crq_get_version failed rc=%d\n", rc);
+@@ -335,7 +338,8 @@ static int tpm_ibmvtpm_suspend(struct de
+       crq.valid = (u8)IBMVTPM_VALID_CMD;
+       crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
+-      rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
++      rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
++                            cpu_to_be64(buf[1]));
+       if (rc != H_SUCCESS)
+               dev_err(ibmvtpm->dev,
+                       "tpm_ibmvtpm_suspend failed rc=%d\n", rc);
+@@ -480,11 +484,11 @@ static void ibmvtpm_crq_process(struct i
+       case IBMVTPM_VALID_CMD:
+               switch (crq->msg) {
+               case VTPM_GET_RTCE_BUFFER_SIZE_RES:
+-                      if (crq->len <= 0) {
++                      if (be16_to_cpu(crq->len) <= 0) {
+                               dev_err(ibmvtpm->dev, "Invalid rtce size\n");
+                               return;
+                       }
+-                      ibmvtpm->rtce_size = crq->len;
++                      ibmvtpm->rtce_size = be16_to_cpu(crq->len);
+                       ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
+                                                   GFP_KERNEL);
+                       if (!ibmvtpm->rtce_buf) {
+@@ -505,11 +509,11 @@ static void ibmvtpm_crq_process(struct i
+                       return;
+               case VTPM_GET_VERSION_RES:
+-                      ibmvtpm->vtpm_version = crq->data;
++                      ibmvtpm->vtpm_version = be32_to_cpu(crq->data);
+                       return;
+               case VTPM_TPM_COMMAND_RES:
+                       /* len of the data in rtce buffer */
+-                      ibmvtpm->res_len = crq->len;
++                      ibmvtpm->res_len = be16_to_cpu(crq->len);
+                       wake_up_interruptible(&ibmvtpm->wq);
+                       return;
+               default:
diff --git a/queue-3.19/cfq-iosched-fix-incorrect-filing-of-rt-async-cfqq.patch b/queue-3.19/cfq-iosched-fix-incorrect-filing-of-rt-async-cfqq.patch
new file mode 100644 (file)
index 0000000..cb4df21
--- /dev/null
@@ -0,0 +1,116 @@
+From c6ce194325cef342313e3d27620411ce90a89c50 Mon Sep 17 00:00:00 2001
+From: Jeff Moyer <jmoyer@redhat.com>
+Date: Mon, 12 Jan 2015 15:21:01 -0500
+Subject: cfq-iosched: fix incorrect filing of rt async cfqq
+
+From: Jeff Moyer <jmoyer@redhat.com>
+
+commit c6ce194325cef342313e3d27620411ce90a89c50 upstream.
+
+Hi,
+
+If you can manage to submit an async write as the first async I/O from
+the context of a process with realtime scheduling priority, then a
+cfq_queue is allocated, but filed into the wrong async_cfqq bucket.  It
+ends up in the best effort array, but actually has realtime I/O
+scheduling priority set in cfqq->ioprio.
+
+The reason is that cfq_get_queue assumes the default scheduling class and
+priority when there is no information present (i.e. when the async cfqq
+is created):
+
+static struct cfq_queue *
+cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic,
+             struct bio *bio, gfp_t gfp_mask)
+{
+       const int ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio);
+       const int ioprio = IOPRIO_PRIO_DATA(cic->ioprio);
+
+cic->ioprio starts out as 0, which is "invalid".  So, class of 0
+(IOPRIO_CLASS_NONE) is passed to cfq_async_queue_prio like so:
+
+               async_cfqq = cfq_async_queue_prio(cfqd, ioprio_class, ioprio);
+
+static struct cfq_queue **
+cfq_async_queue_prio(struct cfq_data *cfqd, int ioprio_class, int ioprio)
+{
+        switch (ioprio_class) {
+        case IOPRIO_CLASS_RT:
+                return &cfqd->async_cfqq[0][ioprio];
+        case IOPRIO_CLASS_NONE:
+                ioprio = IOPRIO_NORM;
+                /* fall through */
+        case IOPRIO_CLASS_BE:
+                return &cfqd->async_cfqq[1][ioprio];
+        case IOPRIO_CLASS_IDLE:
+                return &cfqd->async_idle_cfqq;
+        default:
+                BUG();
+        }
+}
+
+Here, instead of returning a class mapped from the process' scheduling
+priority, we get back the bucket associated with IOPRIO_CLASS_BE.
+
+Now, there is no queue allocated there yet, so we create it:
+
+               cfqq = cfq_find_alloc_queue(cfqd, is_sync, cic, bio, gfp_mask);
+
+That function ends up doing this:
+
+                       cfq_init_cfqq(cfqd, cfqq, current->pid, is_sync);
+                       cfq_init_prio_data(cfqq, cic);
+
+cfq_init_cfqq marks the priority as having changed.  Then, cfq_init_prio
+data does this:
+
+       ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio);
+       switch (ioprio_class) {
+       default:
+               printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class);
+       case IOPRIO_CLASS_NONE:
+               /*
+                * no prio set, inherit CPU scheduling settings
+                */
+               cfqq->ioprio = task_nice_ioprio(tsk);
+               cfqq->ioprio_class = task_nice_ioclass(tsk);
+               break;
+
+So we basically have two code paths that treat IOPRIO_CLASS_NONE
+differently, which results in an RT async cfqq filed into a best effort
+bucket.
+
+Attached is a patch which fixes the problem.  I'm not sure how to make
+it cleaner.  Suggestions would be welcome.
+
+Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
+Tested-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/cfq-iosched.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/block/cfq-iosched.c
++++ b/block/cfq-iosched.c
+@@ -3661,12 +3661,17 @@ static struct cfq_queue *
+ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic,
+             struct bio *bio, gfp_t gfp_mask)
+ {
+-      const int ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio);
+-      const int ioprio = IOPRIO_PRIO_DATA(cic->ioprio);
++      int ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio);
++      int ioprio = IOPRIO_PRIO_DATA(cic->ioprio);
+       struct cfq_queue **async_cfqq = NULL;
+       struct cfq_queue *cfqq = NULL;
+       if (!is_sync) {
++              if (!ioprio_valid(cic->ioprio)) {
++                      struct task_struct *tsk = current;
++                      ioprio = task_nice_ioprio(tsk);
++                      ioprio_class = task_nice_ioclass(tsk);
++              }
+               async_cfqq = cfq_async_queue_prio(cfqd, ioprio_class, ioprio);
+               cfqq = *async_cfqq;
+       }
diff --git a/queue-3.19/cfq-iosched-handle-failure-of-cfq-group-allocation.patch b/queue-3.19/cfq-iosched-handle-failure-of-cfq-group-allocation.patch
new file mode 100644 (file)
index 0000000..ba14954
--- /dev/null
@@ -0,0 +1,54 @@
+From 69abaffec7d47a083739b79e3066cb3730eba72e Mon Sep 17 00:00:00 2001
+From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
+Date: Mon, 9 Feb 2015 16:42:49 +0300
+Subject: cfq-iosched: handle failure of cfq group allocation
+
+From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
+
+commit 69abaffec7d47a083739b79e3066cb3730eba72e upstream.
+
+Cfq_lookup_create_cfqg() allocates struct blkcg_gq using GFP_ATOMIC.
+In cfq_find_alloc_queue() possible allocation failure is not handled.
+As a result kernel oopses on NULL pointer dereference when
+cfq_link_cfqq_cfqg() calls cfqg_get() for NULL pointer.
+
+Bug was introduced in v3.5 in commit cd1604fab4f9 ("blkcg: factor
+out blkio_group creation"). Prior to that commit cfq group lookup
+had returned pointer to root group as fallback.
+
+This patch handles this error using existing fallback oom_cfqq.
+
+Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
+Acked-by: Tejun Heo <tj@kernel.org>
+Acked-by: Vivek Goyal <vgoyal@redhat.com>
+Fixes: cd1604fab4f9 ("blkcg: factor out blkio_group creation")
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/cfq-iosched.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/block/cfq-iosched.c
++++ b/block/cfq-iosched.c
+@@ -3590,6 +3590,11 @@ retry:
+       blkcg = bio_blkcg(bio);
+       cfqg = cfq_lookup_create_cfqg(cfqd, blkcg);
++      if (!cfqg) {
++              cfqq = &cfqd->oom_cfqq;
++              goto out;
++      }
++
+       cfqq = cic_to_cfqq(cic, is_sync);
+       /*
+@@ -3626,7 +3631,7 @@ retry:
+               } else
+                       cfqq = &cfqd->oom_cfqq;
+       }
+-
++out:
+       if (new_cfqq)
+               kmem_cache_free(cfq_pool, new_cfqq);
diff --git a/queue-3.19/char-tpm-add-missing-error-check-for-devm_kzalloc.patch b/queue-3.19/char-tpm-add-missing-error-check-for-devm_kzalloc.patch
new file mode 100644 (file)
index 0000000..ab263a8
--- /dev/null
@@ -0,0 +1,51 @@
+From bb95cd34ba4c9467114acc78eeddd53ab1c10085 Mon Sep 17 00:00:00 2001
+From: Kiran Padwal <kiran.padwal@smartplayin.com>
+Date: Fri, 19 Sep 2014 12:44:39 +0530
+Subject: char: tpm: Add missing error check for devm_kzalloc
+
+From: Kiran Padwal <kiran.padwal@smartplayin.com>
+
+commit bb95cd34ba4c9467114acc78eeddd53ab1c10085 upstream.
+
+Currently these driver are missing a check on the return value of devm_kzalloc,
+which would cause a NULL pointer dereference in a OOM situation.
+
+This patch adds a missing check for tpm_i2c_atmel.c and tpm_i2c_nuvoton.c
+
+Signed-off-by: Kiran Padwal <kiran.padwal@smartplayin.com>
+Reviewed-By: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_i2c_atmel.c   |    4 ++++
+ drivers/char/tpm/tpm_i2c_nuvoton.c |    5 +++++
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/char/tpm/tpm_i2c_atmel.c
++++ b/drivers/char/tpm/tpm_i2c_atmel.c
+@@ -168,6 +168,10 @@ static int i2c_atmel_probe(struct i2c_cl
+       chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data),
+                                        GFP_KERNEL);
++      if (!chip->vendor.priv) {
++              rc = -ENOMEM;
++              goto out_err;
++      }
+       /* Default timeouts */
+       chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
+--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
++++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
+@@ -538,6 +538,11 @@ static int i2c_nuvoton_probe(struct i2c_
+       chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data),
+                                        GFP_KERNEL);
++      if (!chip->vendor.priv) {
++              rc = -ENOMEM;
++              goto out_err;
++      }
++
+       init_waitqueue_head(&chip->vendor.read_queue);
+       init_waitqueue_head(&chip->vendor.int_queue);
diff --git a/queue-3.19/cipso-don-t-use-ipcb-to-locate-the-cipso-ip-option.patch b/queue-3.19/cipso-don-t-use-ipcb-to-locate-the-cipso-ip-option.patch
new file mode 100644 (file)
index 0000000..e779d36
--- /dev/null
@@ -0,0 +1,245 @@
+From 04f81f0154e4bf002be6f4d85668ce1257efa4d9 Mon Sep 17 00:00:00 2001
+From: Paul Moore <pmoore@redhat.com>
+Date: Wed, 11 Feb 2015 14:46:37 -0500
+Subject: cipso: don't use IPCB() to locate the CIPSO IP option
+
+From: Paul Moore <pmoore@redhat.com>
+
+commit 04f81f0154e4bf002be6f4d85668ce1257efa4d9 upstream.
+
+Using the IPCB() macro to get the IPv4 options is convenient, but
+unfortunately NetLabel often needs to examine the CIPSO option outside
+of the scope of the IP layer in the stack.  While historically IPCB()
+worked above the IP layer, due to the inclusion of the inet_skb_param
+struct at the head of the {tcp,udp}_skb_cb structs, recent commit
+971f10ec ("tcp: better TCP_SKB_CB layout to reduce cache line misses")
+reordered the tcp_skb_cb struct and invalidated this IPCB() trick.
+
+This patch fixes the problem by creating a new function,
+cipso_v4_optptr(), which locates the CIPSO option inside the IP header
+without calling IPCB().  Unfortunately, this isn't as fast as a simple
+lookup so some additional tweaks were made to limit the use of this
+new function.
+
+Reported-by: Casey Schaufler <casey@schaufler-ca.com>
+Signed-off-by: Paul Moore <pmoore@redhat.com>
+Tested-by: Casey Schaufler <casey@schaufler-ca.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/cipso_ipv4.h     |   25 +++++++++++++--------
+ net/ipv4/cipso_ipv4.c        |   51 +++++++++++++++++++++++++------------------
+ net/netlabel/netlabel_kapi.c |   15 ++++++++----
+ 3 files changed, 56 insertions(+), 35 deletions(-)
+
+--- a/include/net/cipso_ipv4.h
++++ b/include/net/cipso_ipv4.h
+@@ -121,13 +121,6 @@ extern int cipso_v4_rbm_strictvalid;
+ #endif
+ /*
+- * Helper Functions
+- */
+-
+-#define CIPSO_V4_OPTEXIST(x) (IPCB(x)->opt.cipso != 0)
+-#define CIPSO_V4_OPTPTR(x) (skb_network_header(x) + IPCB(x)->opt.cipso)
+-
+-/*
+  * DOI List Functions
+  */
+@@ -190,7 +183,7 @@ static inline int cipso_v4_doi_domhsh_re
+ #ifdef CONFIG_NETLABEL
+ void cipso_v4_cache_invalidate(void);
+-int cipso_v4_cache_add(const struct sk_buff *skb,
++int cipso_v4_cache_add(const unsigned char *cipso_ptr,
+                      const struct netlbl_lsm_secattr *secattr);
+ #else
+ static inline void cipso_v4_cache_invalidate(void)
+@@ -198,7 +191,7 @@ static inline void cipso_v4_cache_invali
+       return;
+ }
+-static inline int cipso_v4_cache_add(const struct sk_buff *skb,
++static inline int cipso_v4_cache_add(const unsigned char *cipso_ptr,
+                                    const struct netlbl_lsm_secattr *secattr)
+ {
+       return 0;
+@@ -211,6 +204,8 @@ static inline int cipso_v4_cache_add(con
+ #ifdef CONFIG_NETLABEL
+ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
++int cipso_v4_getattr(const unsigned char *cipso,
++                   struct netlbl_lsm_secattr *secattr);
+ int cipso_v4_sock_setattr(struct sock *sk,
+                         const struct cipso_v4_doi *doi_def,
+                         const struct netlbl_lsm_secattr *secattr);
+@@ -226,6 +221,7 @@ int cipso_v4_skbuff_setattr(struct sk_bu
+ int cipso_v4_skbuff_delattr(struct sk_buff *skb);
+ int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
+                           struct netlbl_lsm_secattr *secattr);
++unsigned char *cipso_v4_optptr(const struct sk_buff *skb);
+ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
+ #else
+ static inline void cipso_v4_error(struct sk_buff *skb,
+@@ -235,6 +231,12 @@ static inline void cipso_v4_error(struct
+       return;
+ }
++static inline int cipso_v4_getattr(const unsigned char *cipso,
++                                 struct netlbl_lsm_secattr *secattr)
++{
++      return -ENOSYS;
++}
++
+ static inline int cipso_v4_sock_setattr(struct sock *sk,
+                                     const struct cipso_v4_doi *doi_def,
+                                     const struct netlbl_lsm_secattr *secattr)
+@@ -282,6 +284,11 @@ static inline int cipso_v4_skbuff_getatt
+       return -ENOSYS;
+ }
++static inline unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
++{
++      return NULL;
++}
++
+ static inline int cipso_v4_validate(const struct sk_buff *skb,
+                                   unsigned char **option)
+ {
+--- a/net/ipv4/cipso_ipv4.c
++++ b/net/ipv4/cipso_ipv4.c
+@@ -378,20 +378,18 @@ static int cipso_v4_cache_check(const un
+  * negative values on failure.
+  *
+  */
+-int cipso_v4_cache_add(const struct sk_buff *skb,
++int cipso_v4_cache_add(const unsigned char *cipso_ptr,
+                      const struct netlbl_lsm_secattr *secattr)
+ {
+       int ret_val = -EPERM;
+       u32 bkt;
+       struct cipso_v4_map_cache_entry *entry = NULL;
+       struct cipso_v4_map_cache_entry *old_entry = NULL;
+-      unsigned char *cipso_ptr;
+       u32 cipso_ptr_len;
+       if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0)
+               return 0;
+-      cipso_ptr = CIPSO_V4_OPTPTR(skb);
+       cipso_ptr_len = cipso_ptr[1];
+       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+@@ -1579,6 +1577,33 @@ static int cipso_v4_parsetag_loc(const s
+ }
+ /**
++ * cipso_v4_optptr - Find the CIPSO option in the packet
++ * @skb: the packet
++ *
++ * Description:
++ * Parse the packet's IP header looking for a CIPSO option.  Returns a pointer
++ * to the start of the CIPSO option on success, NULL if one if not found.
++ *
++ */
++unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
++{
++      const struct iphdr *iph = ip_hdr(skb);
++      unsigned char *optptr = (unsigned char *)&(ip_hdr(skb)[1]);
++      int optlen;
++      int taglen;
++
++      for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 0; ) {
++              if (optptr[0] == IPOPT_CIPSO)
++                      return optptr;
++              taglen = optptr[1];
++              optlen -= taglen;
++              optptr += taglen;
++      }
++
++      return NULL;
++}
++
++/**
+  * cipso_v4_validate - Validate a CIPSO option
+  * @option: the start of the option, on error it is set to point to the error
+  *
+@@ -2119,8 +2144,8 @@ void cipso_v4_req_delattr(struct request
+  * on success and negative values on failure.
+  *
+  */
+-static int cipso_v4_getattr(const unsigned char *cipso,
+-                          struct netlbl_lsm_secattr *secattr)
++int cipso_v4_getattr(const unsigned char *cipso,
++                   struct netlbl_lsm_secattr *secattr)
+ {
+       int ret_val = -ENOMSG;
+       u32 doi;
+@@ -2305,22 +2330,6 @@ int cipso_v4_skbuff_delattr(struct sk_bu
+       return 0;
+ }
+-/**
+- * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
+- * @skb: the packet
+- * @secattr: the security attributes
+- *
+- * Description:
+- * Parse the given packet's CIPSO option and return the security attributes.
+- * Returns zero on success and negative values on failure.
+- *
+- */
+-int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
+-                          struct netlbl_lsm_secattr *secattr)
+-{
+-      return cipso_v4_getattr(CIPSO_V4_OPTPTR(skb), secattr);
+-}
+-
+ /*
+  * Setup Functions
+  */
+--- a/net/netlabel/netlabel_kapi.c
++++ b/net/netlabel/netlabel_kapi.c
+@@ -1065,10 +1065,12 @@ int netlbl_skbuff_getattr(const struct s
+                         u16 family,
+                         struct netlbl_lsm_secattr *secattr)
+ {
++      unsigned char *ptr;
++
+       switch (family) {
+       case AF_INET:
+-              if (CIPSO_V4_OPTEXIST(skb) &&
+-                  cipso_v4_skbuff_getattr(skb, secattr) == 0)
++              ptr = cipso_v4_optptr(skb);
++              if (ptr && cipso_v4_getattr(ptr, secattr) == 0)
+                       return 0;
+               break;
+ #if IS_ENABLED(CONFIG_IPV6)
+@@ -1094,7 +1096,7 @@ int netlbl_skbuff_getattr(const struct s
+  */
+ void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
+ {
+-      if (CIPSO_V4_OPTEXIST(skb))
++      if (cipso_v4_optptr(skb))
+               cipso_v4_error(skb, error, gateway);
+ }
+@@ -1126,11 +1128,14 @@ void netlbl_cache_invalidate(void)
+ int netlbl_cache_add(const struct sk_buff *skb,
+                    const struct netlbl_lsm_secattr *secattr)
+ {
++      unsigned char *ptr;
++
+       if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
+               return -ENOMSG;
+-      if (CIPSO_V4_OPTEXIST(skb))
+-              return cipso_v4_cache_add(skb, secattr);
++      ptr = cipso_v4_optptr(skb);
++      if (ptr)
++              return cipso_v4_cache_add(ptr, secattr);
+       return -ENOMSG;
+ }
diff --git a/queue-3.19/iscsi-target-drop-problematic-active_ts_list-usage.patch b/queue-3.19/iscsi-target-drop-problematic-active_ts_list-usage.patch
new file mode 100644 (file)
index 0000000..c47d56a
--- /dev/null
@@ -0,0 +1,133 @@
+From 3fd7b60f2c7418239d586e359e0c6d8503e10646 Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Thu, 22 Jan 2015 00:56:53 -0800
+Subject: iscsi-target: Drop problematic active_ts_list usage
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit 3fd7b60f2c7418239d586e359e0c6d8503e10646 upstream.
+
+This patch drops legacy active_ts_list usage within iscsi_target_tq.c
+code.  It was originally used to track the active thread sets during
+iscsi-target shutdown, and is no longer used by modern upstream code.
+
+Two people have reported list corruption using traditional iscsi-target
+and iser-target with the following backtrace, that appears to be related
+to iscsi_thread_set->ts_list being used across both active_ts_list and
+inactive_ts_list.
+
+[   60.782534] ------------[ cut here ]------------
+[   60.782543] WARNING: CPU: 0 PID: 9430 at lib/list_debug.c:53 __list_del_entry+0x63/0xd0()
+[   60.782545] list_del corruption, ffff88045b00d180->next is LIST_POISON1 (dead000000100100)
+[   60.782546] Modules linked in: ib_srpt tcm_qla2xxx qla2xxx tcm_loop tcm_fc libfc scsi_transport_fc scsi_tgt ib_isert rdma_cm iw_cm ib_addr iscsi_target_mod target_core_pscsi target_core_file target_core_iblock target_core_mod configfs ebtable_nat ebtables ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 ipt_REJECT xt_CHECKSUM iptable_mangle iptable_filter ip_tables bridge stp llc autofs4 sunrpc ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables ipv6 ib_ipoib ib_cm ib_uverbs ib_umad mlx4_en mlx4_ib ib_sa ib_mad ib_core mlx4_core dm_mirror dm_region_hash dm_log dm_mod vhost_net macvtap macvlan vhost tun kvm_intel kvm uinput iTCO_wdt iTCO_vendor_support microcode serio_raw pcspkr sb_edac edac_core sg i2c_i801 lpc_ich mfd_core mtip32xx igb i2c_algo_bit i2c_core ptp pps_core ioatdma dca wmi ext3(F) jbd(F) mbcache(F) sd_mod(F) crc_t10dif(F) crct10dif_common(F) ahci(F) libahci(F) isci(F) libsas(F) scsi_transport_sas(F) [last unloaded: speedstep_lib]
+[   60.782597] CPU: 0 PID: 9430 Comm: iscsi_ttx Tainted: GF 3.12.19+ #2
+[   60.782598] Hardware name: Supermicro X9DRX+-F/X9DRX+-F, BIOS 3.00 07/09/2013
+[   60.782599]  0000000000000035 ffff88044de31d08 ffffffff81553ae7 0000000000000035
+[   60.782602]  ffff88044de31d58 ffff88044de31d48 ffffffff8104d1cc 0000000000000002
+[   60.782605]  ffff88045b00d180 ffff88045b00d0c0 ffff88045b00d0c0 ffff88044de31e58
+[   60.782607] Call Trace:
+[   60.782611]  [<ffffffff81553ae7>] dump_stack+0x49/0x62
+[   60.782615]  [<ffffffff8104d1cc>] warn_slowpath_common+0x8c/0xc0
+[   60.782618]  [<ffffffff8104d2b6>] warn_slowpath_fmt+0x46/0x50
+[   60.782620]  [<ffffffff81280933>] __list_del_entry+0x63/0xd0
+[   60.782622]  [<ffffffff812809b1>] list_del+0x11/0x40
+[   60.782630]  [<ffffffffa06e7cf9>] iscsi_del_ts_from_active_list+0x29/0x50 [iscsi_target_mod]
+[   60.782635]  [<ffffffffa06e87b1>] iscsi_tx_thread_pre_handler+0xa1/0x180 [iscsi_target_mod]
+[   60.782642]  [<ffffffffa06fb9ae>] iscsi_target_tx_thread+0x4e/0x220 [iscsi_target_mod]
+[   60.782647]  [<ffffffffa06fb960>] ? iscsit_handle_snack+0x190/0x190 [iscsi_target_mod]
+[   60.782652]  [<ffffffffa06fb960>] ? iscsit_handle_snack+0x190/0x190 [iscsi_target_mod]
+[   60.782655]  [<ffffffff8106f99e>] kthread+0xce/0xe0
+[   60.782657]  [<ffffffff8106f8d0>] ? kthread_freezable_should_stop+0x70/0x70
+[   60.782660]  [<ffffffff8156026c>] ret_from_fork+0x7c/0xb0
+[   60.782662]  [<ffffffff8106f8d0>] ? kthread_freezable_should_stop+0x70/0x70
+[   60.782663] ---[ end trace 9662f4a661d33965 ]---
+
+Since this code is no longer used, go ahead and drop the problematic usage
+all-together.
+
+Reported-by: Gavin Guo <gavin.guo@canonical.com>
+Reported-by: Moussa Ba <moussaba@micron.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/iscsi/iscsi_target_tq.c |   28 +++++-----------------------
+ 1 file changed, 5 insertions(+), 23 deletions(-)
+
+--- a/drivers/target/iscsi/iscsi_target_tq.c
++++ b/drivers/target/iscsi/iscsi_target_tq.c
+@@ -24,36 +24,22 @@
+ #include "iscsi_target_tq.h"
+ #include "iscsi_target.h"
+-static LIST_HEAD(active_ts_list);
+ static LIST_HEAD(inactive_ts_list);
+-static DEFINE_SPINLOCK(active_ts_lock);
+ static DEFINE_SPINLOCK(inactive_ts_lock);
+ static DEFINE_SPINLOCK(ts_bitmap_lock);
+-static void iscsi_add_ts_to_active_list(struct iscsi_thread_set *ts)
+-{
+-      spin_lock(&active_ts_lock);
+-      list_add_tail(&ts->ts_list, &active_ts_list);
+-      iscsit_global->active_ts++;
+-      spin_unlock(&active_ts_lock);
+-}
+-
+ static void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
+ {
++      if (!list_empty(&ts->ts_list)) {
++              WARN_ON(1);
++              return;
++      }
+       spin_lock(&inactive_ts_lock);
+       list_add_tail(&ts->ts_list, &inactive_ts_list);
+       iscsit_global->inactive_ts++;
+       spin_unlock(&inactive_ts_lock);
+ }
+-static void iscsi_del_ts_from_active_list(struct iscsi_thread_set *ts)
+-{
+-      spin_lock(&active_ts_lock);
+-      list_del(&ts->ts_list);
+-      iscsit_global->active_ts--;
+-      spin_unlock(&active_ts_lock);
+-}
+-
+ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
+ {
+       struct iscsi_thread_set *ts;
+@@ -66,7 +52,7 @@ static struct iscsi_thread_set *iscsi_ge
+       ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list);
+-      list_del(&ts->ts_list);
++      list_del_init(&ts->ts_list);
+       iscsit_global->inactive_ts--;
+       spin_unlock(&inactive_ts_lock);
+@@ -204,8 +190,6 @@ static void iscsi_deallocate_extra_threa
+ void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts)
+ {
+-      iscsi_add_ts_to_active_list(ts);
+-
+       spin_lock_bh(&ts->ts_state_lock);
+       conn->thread_set = ts;
+       ts->conn = conn;
+@@ -397,7 +381,6 @@ struct iscsi_conn *iscsi_rx_thread_pre_h
+       if (ts->delay_inactive && (--ts->thread_count == 0)) {
+               spin_unlock_bh(&ts->ts_state_lock);
+-              iscsi_del_ts_from_active_list(ts);
+               if (!iscsit_global->in_shutdown)
+                       iscsi_deallocate_extra_thread_sets();
+@@ -452,7 +435,6 @@ struct iscsi_conn *iscsi_tx_thread_pre_h
+       if (ts->delay_inactive && (--ts->thread_count == 0)) {
+               spin_unlock_bh(&ts->ts_state_lock);
+-              iscsi_del_ts_from_active_list(ts);
+               if (!iscsit_global->in_shutdown)
+                       iscsi_deallocate_extra_thread_sets();
diff --git a/queue-3.19/nfs41-.init_read-and-.init_write-can-be-called-with-valid-pg_lseg.patch b/queue-3.19/nfs41-.init_read-and-.init_write-can-be-called-with-valid-pg_lseg.patch
new file mode 100644 (file)
index 0000000..1e85bb5
--- /dev/null
@@ -0,0 +1,78 @@
+From cb5d04bc39e914124e811ea55f3034d2379a5f6c Mon Sep 17 00:00:00 2001
+From: Peng Tao <tao.peng@primarydata.com>
+Date: Sat, 24 Jan 2015 22:14:52 +0800
+Subject: nfs41: .init_read and .init_write can be called with valid pg_lseg
+
+From: Peng Tao <tao.peng@primarydata.com>
+
+commit cb5d04bc39e914124e811ea55f3034d2379a5f6c upstream.
+
+With pgio refactoring in v3.15, .init_read and .init_write can be
+called with valid pgio->pg_lseg. file layout was fixed at that time
+by commit c6194271f (pnfs: filelayout: support non page aligned
+layouts). But the generic helper still needs to be fixed.
+
+Signed-off-by: Peng Tao <tao.peng@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/pnfs.c |   41 ++++++++++++++++++++---------------------
+ 1 file changed, 20 insertions(+), 21 deletions(-)
+
+--- a/fs/nfs/pnfs.c
++++ b/fs/nfs/pnfs.c
+@@ -1445,19 +1445,19 @@ pnfs_generic_pg_init_read(struct nfs_pag
+ {
+       u64 rd_size = req->wb_bytes;
+-      WARN_ON_ONCE(pgio->pg_lseg != NULL);
+-
+-      if (pgio->pg_dreq == NULL)
+-              rd_size = i_size_read(pgio->pg_inode) - req_offset(req);
+-      else
+-              rd_size = nfs_dreq_bytes_left(pgio->pg_dreq);
+-
+-      pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
+-                                         req->wb_context,
+-                                         req_offset(req),
+-                                         rd_size,
+-                                         IOMODE_READ,
+-                                         GFP_KERNEL);
++      if (pgio->pg_lseg == NULL) {
++              if (pgio->pg_dreq == NULL)
++                      rd_size = i_size_read(pgio->pg_inode) - req_offset(req);
++              else
++                      rd_size = nfs_dreq_bytes_left(pgio->pg_dreq);
++
++              pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
++                                                 req->wb_context,
++                                                 req_offset(req),
++                                                 rd_size,
++                                                 IOMODE_READ,
++                                                 GFP_KERNEL);
++      }
+       /* If no lseg, fall back to read through mds */
+       if (pgio->pg_lseg == NULL)
+               nfs_pageio_reset_read_mds(pgio);
+@@ -1469,14 +1469,13 @@ void
+ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
+                          struct nfs_page *req, u64 wb_size)
+ {
+-      WARN_ON_ONCE(pgio->pg_lseg != NULL);
+-
+-      pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
+-                                         req->wb_context,
+-                                         req_offset(req),
+-                                         wb_size,
+-                                         IOMODE_RW,
+-                                         GFP_NOFS);
++      if (pgio->pg_lseg == NULL)
++              pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
++                                                 req->wb_context,
++                                                 req_offset(req),
++                                                 wb_size,
++                                                 IOMODE_RW,
++                                                 GFP_NOFS);
+       /* If no lseg, fall back to write through mds */
+       if (pgio->pg_lseg == NULL)
+               nfs_pageio_reset_write_mds(pgio);
diff --git a/queue-3.19/nfsv4-ensure-we-reference-the-inode-for-return-on-close-in-delegreturn.patch b/queue-3.19/nfsv4-ensure-we-reference-the-inode-for-return-on-close-in-delegreturn.patch
new file mode 100644 (file)
index 0000000..6cc48bd
--- /dev/null
@@ -0,0 +1,113 @@
+From ea7c38fef0b774a5dc16fb0ca5935f0ae8568176 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Thu, 5 Feb 2015 15:13:24 -0500
+Subject: NFSv4: Ensure we reference the inode for return-on-close in delegreturn
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit ea7c38fef0b774a5dc16fb0ca5935f0ae8568176 upstream.
+
+If we have to do a return-on-close in the delegreturn code, then
+we must ensure that the inode and super block remain referenced.
+
+Cc: Peng Tao <tao.peng@primarydata.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Reviewed-by: Peng Tao <tao.peng@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/internal.h |   22 +++++++++++++++++++++-
+ fs/nfs/nfs4proc.c |   14 +++++++++-----
+ fs/nfs/super.c    |    9 ++++++---
+ 3 files changed, 36 insertions(+), 9 deletions(-)
+
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -375,7 +375,7 @@ extern struct rpc_stat nfs_rpcstat;
+ extern int __init register_nfs_fs(void);
+ extern void __exit unregister_nfs_fs(void);
+-extern void nfs_sb_active(struct super_block *sb);
++extern bool nfs_sb_active(struct super_block *sb);
+ extern void nfs_sb_deactive(struct super_block *sb);
+ /* namespace.c */
+@@ -493,6 +493,26 @@ extern int nfs41_walk_client_list(struct
+                               struct nfs_client **result,
+                               struct rpc_cred *cred);
++static inline struct inode *nfs_igrab_and_active(struct inode *inode)
++{
++      inode = igrab(inode);
++      if (inode != NULL && !nfs_sb_active(inode->i_sb)) {
++              iput(inode);
++              inode = NULL;
++      }
++      return inode;
++}
++
++static inline void nfs_iput_and_deactive(struct inode *inode)
++{
++      if (inode != NULL) {
++              struct super_block *sb = inode->i_sb;
++
++              iput(inode);
++              nfs_sb_deactive(sb);
++      }
++}
++
+ /*
+  * Determine the device name as a string
+  */
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -5137,9 +5137,13 @@ static void nfs4_delegreturn_done(struct
+ static void nfs4_delegreturn_release(void *calldata)
+ {
+       struct nfs4_delegreturndata *data = calldata;
++      struct inode *inode = data->inode;
+-      if (data->roc)
+-              pnfs_roc_release(data->inode);
++      if (inode) {
++              if (data->roc)
++                      pnfs_roc_release(inode);
++              nfs_iput_and_deactive(inode);
++      }
+       kfree(calldata);
+ }
+@@ -5196,9 +5200,9 @@ static int _nfs4_proc_delegreturn(struct
+       nfs_fattr_init(data->res.fattr);
+       data->timestamp = jiffies;
+       data->rpc_status = 0;
+-      data->inode = inode;
+-      data->roc = list_empty(&NFS_I(inode)->open_files) ?
+-                  pnfs_roc(inode) : false;
++      data->inode = nfs_igrab_and_active(inode);
++      if (data->inode)
++              data->roc = nfs4_roc(inode);
+       task_setup_data.callback_data = data;
+       msg.rpc_argp = &data->args;
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -405,12 +405,15 @@ void __exit unregister_nfs_fs(void)
+       unregister_filesystem(&nfs_fs_type);
+ }
+-void nfs_sb_active(struct super_block *sb)
++bool nfs_sb_active(struct super_block *sb)
+ {
+       struct nfs_server *server = NFS_SB(sb);
+-      if (atomic_inc_return(&server->active) == 1)
+-              atomic_inc(&sb->s_active);
++      if (!atomic_inc_not_zero(&sb->s_active))
++              return false;
++      if (atomic_inc_return(&server->active) != 1)
++              atomic_dec(&sb->s_active);
++      return true;
+ }
+ EXPORT_SYMBOL_GPL(nfs_sb_active);
diff --git a/queue-3.19/nfsv4.1-fix-a-kfree-of-uninitialised-pointers-in-decode_cb_sequence_args.patch b/queue-3.19/nfsv4.1-fix-a-kfree-of-uninitialised-pointers-in-decode_cb_sequence_args.patch
new file mode 100644 (file)
index 0000000..bb0206d
--- /dev/null
@@ -0,0 +1,36 @@
+From d8ba1f971497c19cf80da1ea5391a46a5f9fbd41 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Wed, 11 Feb 2015 17:27:55 -0500
+Subject: NFSv4.1: Fix a kfree() of uninitialised pointers in decode_cb_sequence_args
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit d8ba1f971497c19cf80da1ea5391a46a5f9fbd41 upstream.
+
+If the call to decode_rc_list() fails due to a memory allocation error,
+then we need to truncate the array size to ensure that we only call
+kfree() on those pointer that were allocated.
+
+Reported-by: David Ramos <daramos@stanford.edu>
+Fixes: 4aece6a19cf7f ("nfs41: cb_sequence xdr implementation")
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/callback_xdr.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/nfs/callback_xdr.c
++++ b/fs/nfs/callback_xdr.c
+@@ -464,8 +464,10 @@ static __be32 decode_cb_sequence_args(st
+               for (i = 0; i < args->csa_nrclists; i++) {
+                       status = decode_rc_list(xdr, &args->csa_rclists[i]);
+-                      if (status)
++                      if (status) {
++                              args->csa_nrclists = i;
+                               goto out_free;
++                      }
+               }
+       }
+       status = 0;
index 30ee5ae8bf39e88f54fee33b36faca0215a2771d..f829af18528d9ce31a557a9fc73d74c080d57448 100644 (file)
@@ -92,3 +92,18 @@ arm-dts-tegra20-fix-gr3d-dsi-unit-and-reg-base-addresses.patch
 arm-dts-am335x-bone-usb0-is-hardwired-for-peripheral.patch
 arm-dts-bcm63xx-fix-l2-cache-properties.patch
 tpm_tis-verify-interrupt-during-init.patch
+tpm-add-new-tpms-to-the-tail-of-the-list-to-prevent-inadvertent-change-of-dev.patch
+char-tpm-add-missing-error-check-for-devm_kzalloc.patch
+tpm-fix-null-return-in-tpm_ibmvtpm_get_desired_dma.patch
+tpm-tpm_i2c_stm_st33-fix-potential-bug-in-tpm_stm_i2c_send.patch
+added-little-endian-support-to-vtpm-module.patch
+nfs41-.init_read-and-.init_write-can-be-called-with-valid-pg_lseg.patch
+sunrpc-null-utsname-dereference-on-nfs-umount-during-namespace-cleanup.patch
+nfsv4-ensure-we-reference-the-inode-for-return-on-close-in-delegreturn.patch
+nfsv4.1-fix-a-kfree-of-uninitialised-pointers-in-decode_cb_sequence_args.patch
+sg-fix-unkillable-i-o-wait-deadlock-with-scsi-mq.patch
+sg-fix-ewouldblock-errors-with-scsi-mq.patch
+iscsi-target-drop-problematic-active_ts_list-usage.patch
+cfq-iosched-handle-failure-of-cfq-group-allocation.patch
+cfq-iosched-fix-incorrect-filing-of-rt-async-cfqq.patch
+cipso-don-t-use-ipcb-to-locate-the-cipso-ip-option.patch
diff --git a/queue-3.19/sg-fix-ewouldblock-errors-with-scsi-mq.patch b/queue-3.19/sg-fix-ewouldblock-errors-with-scsi-mq.patch
new file mode 100644 (file)
index 0000000..e398ce8
--- /dev/null
@@ -0,0 +1,54 @@
+From 7772855a996ec6e16944b120ab5ce21050279821 Mon Sep 17 00:00:00 2001
+From: Tony Battersby <tonyb@cybernetics.com>
+Date: Fri, 13 Feb 2015 12:10:58 -0500
+Subject: sg: fix EWOULDBLOCK errors with scsi-mq
+
+From: Tony Battersby <tonyb@cybernetics.com>
+
+commit 7772855a996ec6e16944b120ab5ce21050279821 upstream.
+
+With scsi-mq enabled, userspace programs can get unexpected EWOULDBLOCK
+(a.k.a. EAGAIN) errors when submitting commands to the SCSI generic
+driver.  Fix by calling blk_get_request() with GFP_KERNEL instead of
+GFP_ATOMIC.
+
+Note: to avoid introducing a potential deadlock, this patch should be
+applied after the patch titled "sg: fix unkillable I/O wait deadlock
+with scsi-mq".
+
+Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
+Acked-by: Douglas Gilbert <dgilbert@interlog.com>
+Tested-by: Douglas Gilbert <dgilbert@interlog.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/sg.c |   17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -1695,7 +1695,22 @@ sg_start_req(Sg_request *srp, unsigned c
+                       return -ENOMEM;
+       }
+-      rq = blk_get_request(q, rw, GFP_ATOMIC);
++      /*
++       * NOTE
++       *
++       * With scsi-mq enabled, there are a fixed number of preallocated
++       * requests equal in number to shost->can_queue.  If all of the
++       * preallocated requests are already in use, then using GFP_ATOMIC with
++       * blk_get_request() will return -EWOULDBLOCK, whereas using GFP_KERNEL
++       * will cause blk_get_request() to sleep until an active command
++       * completes, freeing up a request.  Neither option is ideal, but
++       * GFP_KERNEL is the better choice to prevent userspace from getting an
++       * unexpected EWOULDBLOCK.
++       *
++       * With scsi-mq disabled, blk_get_request() with GFP_KERNEL usually
++       * does not sleep except under memory pressure.
++       */
++      rq = blk_get_request(q, rw, GFP_KERNEL);
+       if (IS_ERR(rq)) {
+               kfree(long_cmdp);
+               return PTR_ERR(rq);
diff --git a/queue-3.19/sg-fix-unkillable-i-o-wait-deadlock-with-scsi-mq.patch b/queue-3.19/sg-fix-unkillable-i-o-wait-deadlock-with-scsi-mq.patch
new file mode 100644 (file)
index 0000000..b1120f4
--- /dev/null
@@ -0,0 +1,67 @@
+From 7568615c1054907ea8c7701ab86dad51aa099888 Mon Sep 17 00:00:00 2001
+From: Tony Battersby <tonyb@cybernetics.com>
+Date: Fri, 13 Feb 2015 12:09:44 -0500
+Subject: sg: fix unkillable I/O wait deadlock with scsi-mq
+
+From: Tony Battersby <tonyb@cybernetics.com>
+
+commit 7568615c1054907ea8c7701ab86dad51aa099888 upstream.
+
+When using the write()/read() interface for submitting commands, the
+SCSI generic driver does not call blk_put_request() on a completed SCSI
+command until userspace calls read() to get the command completion.
+Since scsi-mq uses a fixed number of preallocated requests, this makes
+it possible for userspace to exhaust the entire preallocated supply of
+requests.  For places in the kernel that call blk_get_request() with
+GFP_KERNEL, this can cause the calling process to deadlock in a
+permanent unkillable I/O wait in blk_get_request() -> ... -> bt_get().
+For places in the kernel that call blk_get_request() with GFP_ATOMIC,
+this can cause blk_get_request() always to return -EWOULDBLOCK.  Note
+that these problems happen only if scsi-mq is enabled.  Prevent the
+problems by calling blk_put_request() as soon as the SCSI command
+completes instead of waiting for userspace to call read().
+
+Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
+Acked-by: Douglas Gilbert <dgilbert@interlog.com>
+Tested-by: Douglas Gilbert <dgilbert@interlog.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/sg.c |   17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -1350,6 +1350,17 @@ sg_rq_end_io(struct request *rq, int upt
+       }
+       /* Rely on write phase to clean out srp status values, so no "else" */
++      /*
++       * Free the request as soon as it is complete so that its resources
++       * can be reused without waiting for userspace to read() the
++       * result.  But keep the associated bio (if any) around until
++       * blk_rq_unmap_user() can be called from user context.
++       */
++      srp->rq = NULL;
++      if (rq->cmd != rq->__cmd)
++              kfree(rq->cmd);
++      __blk_put_request(rq->q, rq);
++
+       write_lock_irqsave(&sfp->rq_list_lock, iflags);
+       if (unlikely(srp->orphan)) {
+               if (sfp->keep_orphan)
+@@ -1777,10 +1788,10 @@ sg_finish_rem_req(Sg_request *srp)
+       SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp,
+                                     "sg_finish_rem_req: res_used=%d\n",
+                                     (int) srp->res_used));
+-      if (srp->rq) {
+-              if (srp->bio)
+-                      ret = blk_rq_unmap_user(srp->bio);
++      if (srp->bio)
++              ret = blk_rq_unmap_user(srp->bio);
++      if (srp->rq) {
+               if (srp->rq->cmd != srp->rq->__cmd)
+                       kfree(srp->rq->cmd);
+               blk_put_request(srp->rq);
diff --git a/queue-3.19/sunrpc-null-utsname-dereference-on-nfs-umount-during-namespace-cleanup.patch b/queue-3.19/sunrpc-null-utsname-dereference-on-nfs-umount-during-namespace-cleanup.patch
new file mode 100644 (file)
index 0000000..d3111db
--- /dev/null
@@ -0,0 +1,183 @@
+From 03a9a42a1a7e5b3e7919ddfacc1d1cc81882a955 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Fri, 30 Jan 2015 18:12:28 -0500
+Subject: SUNRPC: NULL utsname dereference on NFS umount during namespace cleanup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit 03a9a42a1a7e5b3e7919ddfacc1d1cc81882a955 upstream.
+
+Fix an Oopsable condition when nsm_mon_unmon is called as part of the
+namespace cleanup, which now apparently happens after the utsname
+has been freed.
+
+Link: http://lkml.kernel.org/r/20150125220604.090121ae@neptune.home
+Reported-by: Bruno PrĂ©mont <bonbons@linux-vserver.org>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/lockd/mon.c              |   13 +++++++++----
+ include/linux/sunrpc/clnt.h |    3 ++-
+ net/sunrpc/clnt.c           |   12 +++++++-----
+ net/sunrpc/rpcb_clnt.c      |    8 ++++++--
+ 4 files changed, 24 insertions(+), 12 deletions(-)
+
+--- a/fs/lockd/mon.c
++++ b/fs/lockd/mon.c
+@@ -65,7 +65,7 @@ static inline struct sockaddr *nsm_addr(
+       return (struct sockaddr *)&nsm->sm_addr;
+ }
+-static struct rpc_clnt *nsm_create(struct net *net)
++static struct rpc_clnt *nsm_create(struct net *net, const char *nodename)
+ {
+       struct sockaddr_in sin = {
+               .sin_family             = AF_INET,
+@@ -77,6 +77,7 @@ static struct rpc_clnt *nsm_create(struc
+               .address                = (struct sockaddr *)&sin,
+               .addrsize               = sizeof(sin),
+               .servername             = "rpc.statd",
++              .nodename               = nodename,
+               .program                = &nsm_program,
+               .version                = NSM_VERSION,
+               .authflavor             = RPC_AUTH_NULL,
+@@ -102,7 +103,7 @@ out:
+       return clnt;
+ }
+-static struct rpc_clnt *nsm_client_get(struct net *net)
++static struct rpc_clnt *nsm_client_get(struct net *net, const char *nodename)
+ {
+       struct rpc_clnt *clnt, *new;
+       struct lockd_net *ln = net_generic(net, lockd_net_id);
+@@ -111,7 +112,7 @@ static struct rpc_clnt *nsm_client_get(s
+       if (clnt != NULL)
+               goto out;
+-      clnt = new = nsm_create(net);
++      clnt = new = nsm_create(net, nodename);
+       if (IS_ERR(clnt))
+               goto out;
+@@ -190,19 +191,23 @@ int nsm_monitor(const struct nlm_host *h
+       struct nsm_res  res;
+       int             status;
+       struct rpc_clnt *clnt;
++      const char *nodename = NULL;
+       dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
+       if (nsm->sm_monitored)
+               return 0;
++      if (host->h_rpcclnt)
++              nodename = host->h_rpcclnt->cl_nodename;
++
+       /*
+        * Choose whether to record the caller_name or IP address of
+        * this peer in the local rpc.statd's database.
+        */
+       nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
+-      clnt = nsm_client_get(host->net);
++      clnt = nsm_client_get(host->net, nodename);
+       if (IS_ERR(clnt)) {
+               status = PTR_ERR(clnt);
+               dprintk("lockd: failed to create NSM upcall transport, "
+--- a/include/linux/sunrpc/clnt.h
++++ b/include/linux/sunrpc/clnt.h
+@@ -57,7 +57,7 @@ struct rpc_clnt {
+       const struct rpc_timeout *cl_timeout;   /* Timeout strategy */
+       int                     cl_nodelen;     /* nodename length */
+-      char                    cl_nodename[UNX_MAXNODENAME];
++      char                    cl_nodename[UNX_MAXNODENAME+1];
+       struct rpc_pipe_dir_head cl_pipedir_objects;
+       struct rpc_clnt *       cl_parent;      /* Points to parent of clones */
+       struct rpc_rtt          cl_rtt_default;
+@@ -112,6 +112,7 @@ struct rpc_create_args {
+       struct sockaddr         *saddress;
+       const struct rpc_timeout *timeout;
+       const char              *servername;
++      const char              *nodename;
+       const struct rpc_program *program;
+       u32                     prognumber;     /* overrides program->number */
+       u32                     version;
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -286,10 +286,8 @@ static struct rpc_xprt *rpc_clnt_set_tra
+ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
+ {
+-      clnt->cl_nodelen = strlen(nodename);
+-      if (clnt->cl_nodelen > UNX_MAXNODENAME)
+-              clnt->cl_nodelen = UNX_MAXNODENAME;
+-      memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen);
++      clnt->cl_nodelen = strlcpy(clnt->cl_nodename,
++                      nodename, sizeof(clnt->cl_nodename));
+ }
+ static int rpc_client_register(struct rpc_clnt *clnt,
+@@ -365,6 +363,7 @@ static struct rpc_clnt * rpc_new_client(
+       const struct rpc_version *version;
+       struct rpc_clnt *clnt = NULL;
+       const struct rpc_timeout *timeout;
++      const char *nodename = args->nodename;
+       int err;
+       /* sanity check the name before trying to print it */
+@@ -420,8 +419,10 @@ static struct rpc_clnt * rpc_new_client(
+       atomic_set(&clnt->cl_count, 1);
++      if (nodename == NULL)
++              nodename = utsname()->nodename;
+       /* save the nodename */
+-      rpc_clnt_set_nodename(clnt, utsname()->nodename);
++      rpc_clnt_set_nodename(clnt, nodename);
+       err = rpc_client_register(clnt, args->authflavor, args->client_name);
+       if (err)
+@@ -576,6 +577,7 @@ static struct rpc_clnt *__rpc_clone_clie
+       if (xprt == NULL)
+               goto out_err;
+       args->servername = xprt->servername;
++      args->nodename = clnt->cl_nodename;
+       new = rpc_new_client(args, xprt, clnt);
+       if (IS_ERR(new)) {
+--- a/net/sunrpc/rpcb_clnt.c
++++ b/net/sunrpc/rpcb_clnt.c
+@@ -355,7 +355,8 @@ out:
+       return result;
+ }
+-static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname,
++static struct rpc_clnt *rpcb_create(struct net *net, const char *nodename,
++                                  const char *hostname,
+                                   struct sockaddr *srvaddr, size_t salen,
+                                   int proto, u32 version)
+ {
+@@ -365,6 +366,7 @@ static struct rpc_clnt *rpcb_create(stru
+               .address        = srvaddr,
+               .addrsize       = salen,
+               .servername     = hostname,
++              .nodename       = nodename,
+               .program        = &rpcb_program,
+               .version        = version,
+               .authflavor     = RPC_AUTH_UNIX,
+@@ -740,7 +742,9 @@ void rpcb_getport_async(struct rpc_task
+       dprintk("RPC: %5u %s: trying rpcbind version %u\n",
+               task->tk_pid, __func__, bind_version);
+-      rpcb_clnt = rpcb_create(xprt->xprt_net, xprt->servername, sap, salen,
++      rpcb_clnt = rpcb_create(xprt->xprt_net,
++                              clnt->cl_nodename,
++                              xprt->servername, sap, salen,
+                               xprt->prot, bind_version);
+       if (IS_ERR(rpcb_clnt)) {
+               status = PTR_ERR(rpcb_clnt);
diff --git a/queue-3.19/tpm-add-new-tpms-to-the-tail-of-the-list-to-prevent-inadvertent-change-of-dev.patch b/queue-3.19/tpm-add-new-tpms-to-the-tail-of-the-list-to-prevent-inadvertent-change-of-dev.patch
new file mode 100644 (file)
index 0000000..a2d6ea9
--- /dev/null
@@ -0,0 +1,34 @@
+From 398a1e71dc827b994b7f2f56c7c2186fea7f8d75 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 29 Aug 2014 10:33:02 +0100
+Subject: TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev
+
+From: David Howells <dhowells@redhat.com>
+
+commit 398a1e71dc827b994b7f2f56c7c2186fea7f8d75 upstream.
+
+Add newly registered TPMs to the tail of the list, not the beginning, so that
+things that are specifying TPM_ANY_NUM don't find that the device they're
+using has inadvertently changed.  Adding a second device would break IMA, for
+instance.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm-interface.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/tpm/tpm-interface.c
++++ b/drivers/char/tpm/tpm-interface.c
+@@ -1122,7 +1122,7 @@ struct tpm_chip *tpm_register_hardware(s
+       /* Make chip available */
+       spin_lock(&driver_lock);
+-      list_add_rcu(&chip->list, &tpm_chip_list);
++      list_add_tail_rcu(&chip->list, &tpm_chip_list);
+       spin_unlock(&driver_lock);
+       return chip;
diff --git a/queue-3.19/tpm-fix-null-return-in-tpm_ibmvtpm_get_desired_dma.patch b/queue-3.19/tpm-fix-null-return-in-tpm_ibmvtpm_get_desired_dma.patch
new file mode 100644 (file)
index 0000000..3734fd8
--- /dev/null
@@ -0,0 +1,49 @@
+From 84eb186bc37c0900b53077ca21cf6dd15823a232 Mon Sep 17 00:00:00 2001
+From: "Hon Ching (Vicky) Lo" <honclo@linux.vnet.ibm.com>
+Date: Sun, 30 Nov 2014 15:01:28 +0100
+Subject: tpm: Fix NULL return in tpm_ibmvtpm_get_desired_dma
+
+From: "Hon Ching (Vicky) Lo" <honclo@linux.vnet.ibm.com>
+
+commit 84eb186bc37c0900b53077ca21cf6dd15823a232 upstream.
+
+There was an oops in tpm_ibmvtpm_get_desired_dma, which caused
+kernel panic during boot when vTPM is enabled in Power partition
+configured in AMS mode.
+
+vio_bus_probe calls vio_cmo_bus_probe which calls
+tpm_ibmvtpm_get_desired_dma to get the size needed for DMA allocation.
+The problem is, vio_cmo_bus_probe is called before calling probe, which
+for vtpm is tpm_ibmvtpm_probe and it's this function that initializes
+and sets up vtpm's CRQ and gets required data values.  Therefore,
+since this has not yet been done, NULL is returned in attempt to get
+the size for DMA allocation.
+
+We added a NULL check.  In addition, a default buffer size will
+be set when NULL is returned.
+
+Signed-off-by: Hon Ching (Vicky) Lo <honclo@linux.vnet.ibm.com>
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_ibmvtpm.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/char/tpm/tpm_ibmvtpm.c
++++ b/drivers/char/tpm/tpm_ibmvtpm.c
+@@ -307,6 +307,14 @@ static int tpm_ibmvtpm_remove(struct vio
+ static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
+ {
+       struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
++
++      /* ibmvtpm initializes at probe time, so the data we are
++      * asking for may not be set yet. Estimate that 4K required
++      * for TCE-mapped buffer in addition to CRQ.
++      */
++      if (!ibmvtpm)
++              return CRQ_RES_BUF_SIZE + PAGE_SIZE;
++
+       return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size;
+ }
diff --git a/queue-3.19/tpm-tpm_i2c_stm_st33-fix-potential-bug-in-tpm_stm_i2c_send.patch b/queue-3.19/tpm-tpm_i2c_stm_st33-fix-potential-bug-in-tpm_stm_i2c_send.patch
new file mode 100644 (file)
index 0000000..384752b
--- /dev/null
@@ -0,0 +1,37 @@
+From 1ba3b0b6f218072afe8372d12f1b6bf26a26008e Mon Sep 17 00:00:00 2001
+From: Christophe Ricard <christophe.ricard@gmail.com>
+Date: Mon, 1 Dec 2014 19:32:46 +0100
+Subject: tpm/tpm_i2c_stm_st33: Fix potential bug in tpm_stm_i2c_send
+
+From: Christophe Ricard <christophe.ricard@gmail.com>
+
+commit 1ba3b0b6f218072afe8372d12f1b6bf26a26008e upstream.
+
+When sending data in tpm_stm_i2c_send, each loop iteration send buf.
+Send buf + i instead as the goal of this for loop is to send a number
+of byte from buf that fit in burstcnt. Once those byte are sent, we are
+supposed to send the next ones.
+
+The driver was working because the burstcount value returns always the maximum size for a TPM
+command or response. (0x800 for a command and 0x400 for a response).
+
+Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_i2c_stm_st33.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/tpm/tpm_i2c_stm_st33.c
++++ b/drivers/char/tpm/tpm_i2c_stm_st33.c
+@@ -487,7 +487,7 @@ static int tpm_stm_i2c_send(struct tpm_c
+               if (burstcnt < 0)
+                       return burstcnt;
+               size = min_t(int, len - i - 1, burstcnt);
+-              ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size);
++              ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + i, size);
+               if (ret < 0)
+                       goto out_err;