From: Greg Kroah-Hartman Date: Sat, 28 Feb 2015 23:06:06 +0000 (-0800) Subject: 3.19-stable patches X-Git-Tag: v3.10.71~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fb91edb1fd84a83e3b39a4518678e8a5bd3e6248;p=thirdparty%2Fkernel%2Fstable-queue.git 3.19-stable patches 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 --- 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 index 00000000000..d1176366b46 --- /dev/null +++ b/queue-3.19/added-little-endian-support-to-vtpm-module.patch @@ -0,0 +1,100 @@ +From eb71f8a5e33fa1066fb92f0111ab366a341e1f6c Mon Sep 17 00:00:00 2001 +From: honclo +Date: Thu, 12 Feb 2015 21:02:24 -0500 +Subject: Added Little Endian support to vtpm module + +From: honclo + +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 +Signed-off-by: Joy Latten +[phuewe: manually applied the patch :( ] +Reviewed-by: Ashley Lai +Signed-off-by: Peter Huewe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..cb4df2162ab --- /dev/null +++ b/queue-3.19/cfq-iosched-fix-incorrect-filing-of-rt-async-cfqq.patch @@ -0,0 +1,116 @@ +From c6ce194325cef342313e3d27620411ce90a89c50 Mon Sep 17 00:00:00 2001 +From: Jeff Moyer +Date: Mon, 12 Jan 2015 15:21:01 -0500 +Subject: cfq-iosched: fix incorrect filing of rt async cfqq + +From: Jeff Moyer + +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 +Tested-by: Hidehiro Kawai +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..ba14954f5fc --- /dev/null +++ b/queue-3.19/cfq-iosched-handle-failure-of-cfq-group-allocation.patch @@ -0,0 +1,54 @@ +From 69abaffec7d47a083739b79e3066cb3730eba72e Mon Sep 17 00:00:00 2001 +From: Konstantin Khlebnikov +Date: Mon, 9 Feb 2015 16:42:49 +0300 +Subject: cfq-iosched: handle failure of cfq group allocation + +From: Konstantin Khlebnikov + +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 +Acked-by: Tejun Heo +Acked-by: Vivek Goyal +Fixes: cd1604fab4f9 ("blkcg: factor out blkio_group creation") +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..ab263a8858e --- /dev/null +++ b/queue-3.19/char-tpm-add-missing-error-check-for-devm_kzalloc.patch @@ -0,0 +1,51 @@ +From bb95cd34ba4c9467114acc78eeddd53ab1c10085 Mon Sep 17 00:00:00 2001 +From: Kiran Padwal +Date: Fri, 19 Sep 2014 12:44:39 +0530 +Subject: char: tpm: Add missing error check for devm_kzalloc + +From: Kiran Padwal + +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 +Reviewed-By: Jason Gunthorpe +Signed-off-by: Peter Huewe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..e779d36626b --- /dev/null +++ b/queue-3.19/cipso-don-t-use-ipcb-to-locate-the-cipso-ip-option.patch @@ -0,0 +1,245 @@ +From 04f81f0154e4bf002be6f4d85668ce1257efa4d9 Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Wed, 11 Feb 2015 14:46:37 -0500 +Subject: cipso: don't use IPCB() to locate the CIPSO IP option + +From: Paul Moore + +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 +Signed-off-by: Paul Moore +Tested-by: Casey Schaufler +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..c47d56a5788 --- /dev/null +++ b/queue-3.19/iscsi-target-drop-problematic-active_ts_list-usage.patch @@ -0,0 +1,133 @@ +From 3fd7b60f2c7418239d586e359e0c6d8503e10646 Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Thu, 22 Jan 2015 00:56:53 -0800 +Subject: iscsi-target: Drop problematic active_ts_list usage + +From: Nicholas Bellinger + +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] [] dump_stack+0x49/0x62 +[ 60.782615] [] warn_slowpath_common+0x8c/0xc0 +[ 60.782618] [] warn_slowpath_fmt+0x46/0x50 +[ 60.782620] [] __list_del_entry+0x63/0xd0 +[ 60.782622] [] list_del+0x11/0x40 +[ 60.782630] [] iscsi_del_ts_from_active_list+0x29/0x50 [iscsi_target_mod] +[ 60.782635] [] iscsi_tx_thread_pre_handler+0xa1/0x180 [iscsi_target_mod] +[ 60.782642] [] iscsi_target_tx_thread+0x4e/0x220 [iscsi_target_mod] +[ 60.782647] [] ? iscsit_handle_snack+0x190/0x190 [iscsi_target_mod] +[ 60.782652] [] ? iscsit_handle_snack+0x190/0x190 [iscsi_target_mod] +[ 60.782655] [] kthread+0xce/0xe0 +[ 60.782657] [] ? kthread_freezable_should_stop+0x70/0x70 +[ 60.782660] [] ret_from_fork+0x7c/0xb0 +[ 60.782662] [] ? 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 +Reported-by: Moussa Ba +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..1e85bb5f13a --- /dev/null +++ b/queue-3.19/nfs41-.init_read-and-.init_write-can-be-called-with-valid-pg_lseg.patch @@ -0,0 +1,78 @@ +From cb5d04bc39e914124e811ea55f3034d2379a5f6c Mon Sep 17 00:00:00 2001 +From: Peng Tao +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 + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..6cc48bd357d --- /dev/null +++ b/queue-3.19/nfsv4-ensure-we-reference-the-inode-for-return-on-close-in-delegreturn.patch @@ -0,0 +1,113 @@ +From ea7c38fef0b774a5dc16fb0ca5935f0ae8568176 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +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 + +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 +Signed-off-by: Trond Myklebust +Reviewed-by: Peng Tao +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..bb0206d282c --- /dev/null +++ b/queue-3.19/nfsv4.1-fix-a-kfree-of-uninitialised-pointers-in-decode_cb_sequence_args.patch @@ -0,0 +1,36 @@ +From d8ba1f971497c19cf80da1ea5391a46a5f9fbd41 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +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 + +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 +Fixes: 4aece6a19cf7f ("nfs41: cb_sequence xdr implementation") +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-3.19/series b/queue-3.19/series index 30ee5ae8bf3..f829af18528 100644 --- a/queue-3.19/series +++ b/queue-3.19/series @@ -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 index 00000000000..e398ce81627 --- /dev/null +++ b/queue-3.19/sg-fix-ewouldblock-errors-with-scsi-mq.patch @@ -0,0 +1,54 @@ +From 7772855a996ec6e16944b120ab5ce21050279821 Mon Sep 17 00:00:00 2001 +From: Tony Battersby +Date: Fri, 13 Feb 2015 12:10:58 -0500 +Subject: sg: fix EWOULDBLOCK errors with scsi-mq + +From: Tony Battersby + +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 +Acked-by: Douglas Gilbert +Tested-by: Douglas Gilbert +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..b1120f45fc6 --- /dev/null +++ b/queue-3.19/sg-fix-unkillable-i-o-wait-deadlock-with-scsi-mq.patch @@ -0,0 +1,67 @@ +From 7568615c1054907ea8c7701ab86dad51aa099888 Mon Sep 17 00:00:00 2001 +From: Tony Battersby +Date: Fri, 13 Feb 2015 12:09:44 -0500 +Subject: sg: fix unkillable I/O wait deadlock with scsi-mq + +From: Tony Battersby + +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 +Acked-by: Douglas Gilbert +Tested-by: Douglas Gilbert +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d3111dbaca8 --- /dev/null +++ b/queue-3.19/sunrpc-null-utsname-dereference-on-nfs-umount-during-namespace-cleanup.patch @@ -0,0 +1,183 @@ +From 03a9a42a1a7e5b3e7919ddfacc1d1cc81882a955 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +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 + +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 +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..a2d6ea96607 --- /dev/null +++ b/queue-3.19/tpm-add-new-tpms-to-the-tail-of-the-list-to-prevent-inadvertent-change-of-dev.patch @@ -0,0 +1,34 @@ +From 398a1e71dc827b994b7f2f56c7c2186fea7f8d75 Mon Sep 17 00:00:00 2001 +From: David Howells +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 + +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 +Reviewed-by: Jason Gunthorpe +Signed-off-by: Peter Huewe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..3734fd8164d --- /dev/null +++ b/queue-3.19/tpm-fix-null-return-in-tpm_ibmvtpm_get_desired_dma.patch @@ -0,0 +1,49 @@ +From 84eb186bc37c0900b53077ca21cf6dd15823a232 Mon Sep 17 00:00:00 2001 +From: "Hon Ching (Vicky) Lo" +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" + +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 +Signed-off-by: Peter Huewe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..384752b9929 --- /dev/null +++ b/queue-3.19/tpm-tpm_i2c_stm_st33-fix-potential-bug-in-tpm_stm_i2c_send.patch @@ -0,0 +1,37 @@ +From 1ba3b0b6f218072afe8372d12f1b6bf26a26008e Mon Sep 17 00:00:00 2001 +From: Christophe Ricard +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 + +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 +Signed-off-by: Christophe Ricard +Signed-off-by: Peter Huewe +Signed-off-by: Greg Kroah-Hartman + +--- + 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; +