From: Greg Kroah-Hartman Date: Mon, 9 Jun 2014 22:10:54 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.14.7~16 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=93107a66356fdd232e533bc7a60445103e146c32;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: iscsi-target-fix-wrong-buffer-buffer-overrun-in-iscsi_change_param_value.patch iser-target-add-missing-target_put_sess_cmd-for-immedatedata-failure.patch mm-add-pte_present-check-on-existing-hugetlb_entry-callbacks.patch mm-rmap-fix-use-after-free-in-__put_anon_vma.patch target-fix-alua_access_state-attribute-oops-for-un-configured-devices.patch --- diff --git a/queue-3.14/iscsi-target-fix-wrong-buffer-buffer-overrun-in-iscsi_change_param_value.patch b/queue-3.14/iscsi-target-fix-wrong-buffer-buffer-overrun-in-iscsi_change_param_value.patch new file mode 100644 index 00000000000..41c2d6b5de7 --- /dev/null +++ b/queue-3.14/iscsi-target-fix-wrong-buffer-buffer-overrun-in-iscsi_change_param_value.patch @@ -0,0 +1,145 @@ +From 79d59d08082dd0a0a18f8ceb78c99f9f321d72aa Mon Sep 17 00:00:00 2001 +From: Roland Dreier +Date: Thu, 29 May 2014 13:32:30 -0700 +Subject: iscsi-target: Fix wrong buffer / buffer overrun in iscsi_change_param_value() + +From: Roland Dreier + +commit 79d59d08082dd0a0a18f8ceb78c99f9f321d72aa upstream. + +In non-leading connection login, iscsi_login_non_zero_tsih_s1() calls +iscsi_change_param_value() with the buffer it uses to hold the login +PDU, not a temporary buffer. This leads to the login header getting +corrupted and login failing for non-leading connections in MC/S. + +Fix this by adding a wrapper iscsi_change_param_sprintf() that handles +the temporary buffer itself to avoid confusion. Also handle sending a +reject in case of failure in the wrapper, which lets the calling code +get quite a bit smaller and easier to read. + +Finally, bump the size of the temporary buffer from 32 to 64 bytes to be +safe, since "MaxRecvDataSegmentLength=" by itself is 25 bytes; with a +trailing NUL, a value >= 1M will lead to a buffer overrun. (This isn't +the default but we don't need to run right at the ragged edge here) + +Reported-by: Santosh Kulkarni +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target_login.c | 57 ++++++++++++++---------------- + 1 file changed, 28 insertions(+), 29 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -249,6 +249,28 @@ static void iscsi_login_set_conn_values( + mutex_unlock(&auth_id_lock); + } + ++static __printf(2, 3) int iscsi_change_param_sprintf( ++ struct iscsi_conn *conn, ++ const char *fmt, ...) ++{ ++ va_list args; ++ unsigned char buf[64]; ++ ++ memset(buf, 0, sizeof buf); ++ ++ va_start(args, fmt); ++ vsnprintf(buf, sizeof buf, fmt, args); ++ va_end(args); ++ ++ if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ++ ISCSI_LOGIN_STATUS_NO_RESOURCES); ++ return -1; ++ } ++ ++ return 0; ++} ++ + /* + * This is the leading connection of a new session, + * or session reinstatement. +@@ -337,7 +359,6 @@ static int iscsi_login_zero_tsih_s2( + { + struct iscsi_node_attrib *na; + struct iscsi_session *sess = conn->sess; +- unsigned char buf[32]; + bool iser = false; + + sess->tpg = conn->tpg; +@@ -378,26 +399,16 @@ static int iscsi_login_zero_tsih_s2( + * + * In our case, we have already located the struct iscsi_tiqn at this point. + */ +- memset(buf, 0, 32); +- sprintf(buf, "TargetPortalGroupTag=%hu", sess->tpg->tpgt); +- if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) { +- iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, +- ISCSI_LOGIN_STATUS_NO_RESOURCES); ++ if (iscsi_change_param_sprintf(conn, "TargetPortalGroupTag=%hu", sess->tpg->tpgt)) + return -1; +- } + + /* + * Workaround for Initiators that have broken connection recovery logic. + * + * "We would really like to get rid of this." Linux-iSCSI.org team + */ +- memset(buf, 0, 32); +- sprintf(buf, "ErrorRecoveryLevel=%d", na->default_erl); +- if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) { +- iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, +- ISCSI_LOGIN_STATUS_NO_RESOURCES); ++ if (iscsi_change_param_sprintf(conn, "ErrorRecoveryLevel=%d", na->default_erl)) + return -1; +- } + + if (iscsi_login_disable_FIM_keys(conn->param_list, conn) < 0) + return -1; +@@ -409,12 +420,9 @@ static int iscsi_login_zero_tsih_s2( + unsigned long mrdsl, off; + int rc; + +- sprintf(buf, "RDMAExtensions=Yes"); +- if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) { +- iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, +- ISCSI_LOGIN_STATUS_NO_RESOURCES); ++ if (iscsi_change_param_sprintf(conn, "RDMAExtensions=Yes")) + return -1; +- } ++ + /* + * Make MaxRecvDataSegmentLength PAGE_SIZE aligned for + * Immediate Data + Unsolicitied Data-OUT if necessary.. +@@ -444,12 +452,8 @@ static int iscsi_login_zero_tsih_s2( + pr_warn("Aligning ISER MaxRecvDataSegmentLength: %lu down" + " to PAGE_SIZE\n", mrdsl); + +- sprintf(buf, "MaxRecvDataSegmentLength=%lu\n", mrdsl); +- if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) { +- iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, +- ISCSI_LOGIN_STATUS_NO_RESOURCES); ++ if (iscsi_change_param_sprintf(conn, "MaxRecvDataSegmentLength=%lu\n", mrdsl)) + return -1; +- } + } + + return 0; +@@ -591,13 +595,8 @@ static int iscsi_login_non_zero_tsih_s2( + * + * In our case, we have already located the struct iscsi_tiqn at this point. + */ +- memset(buf, 0, 32); +- sprintf(buf, "TargetPortalGroupTag=%hu", sess->tpg->tpgt); +- if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) { +- iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, +- ISCSI_LOGIN_STATUS_NO_RESOURCES); ++ if (iscsi_change_param_sprintf(conn, "TargetPortalGroupTag=%hu", sess->tpg->tpgt)) + return -1; +- } + + return iscsi_login_disable_FIM_keys(conn->param_list, conn); + } diff --git a/queue-3.14/iser-target-add-missing-target_put_sess_cmd-for-immedatedata-failure.patch b/queue-3.14/iser-target-add-missing-target_put_sess_cmd-for-immedatedata-failure.patch new file mode 100644 index 00000000000..d670fee1a04 --- /dev/null +++ b/queue-3.14/iser-target-add-missing-target_put_sess_cmd-for-immedatedata-failure.patch @@ -0,0 +1,43 @@ +From 6cc44a6fb46e1ecc1c28125aa8fa34d317aa9ea7 Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Fri, 23 May 2014 00:48:35 -0700 +Subject: iser-target: Add missing target_put_sess_cmd for ImmedateData failure + +From: Nicholas Bellinger + +commit 6cc44a6fb46e1ecc1c28125aa8fa34d317aa9ea7 upstream. + +This patch addresses a bug where an early exception for SCSI WRITE +with ImmediateData=Yes was missing the target_put_sess_cmd() call +to drop the extra se_cmd->cmd_kref reference obtained during the +normal iscsit_setup_scsi_cmd() codepath execution. + +This bug was manifesting itself during session shutdown within +isert_cq_rx_comp_err() where target_wait_for_sess_cmds() would +end up waiting indefinately for the last se_cmd->cmd_kref put to +occur for the failed SCSI WRITE + ImmediateData descriptors. + +This fix follows what traditional iscsi-target code already does +for the same failure case within iscsit_get_immediate_data(). + +Reported-by: Sagi Grimberg +Cc: Sagi Grimberg +Cc: Or Gerlitz +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/ulp/isert/ib_isert.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -1117,6 +1117,8 @@ sequence_cmd: + + if (!rc && dump_payload == false && unsol_data) + iscsit_set_unsoliticed_dataout(cmd); ++ else if (dump_payload && imm_data) ++ target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); + + return 0; + } diff --git a/queue-3.14/mm-add-pte_present-check-on-existing-hugetlb_entry-callbacks.patch b/queue-3.14/mm-add-pte_present-check-on-existing-hugetlb_entry-callbacks.patch new file mode 100644 index 00000000000..1b91816b48b --- /dev/null +++ b/queue-3.14/mm-add-pte_present-check-on-existing-hugetlb_entry-callbacks.patch @@ -0,0 +1,69 @@ +From d4c54919ed86302094c0ca7d48a8cbd4ee753e92 Mon Sep 17 00:00:00 2001 +From: Naoya Horiguchi +Date: Fri, 6 Jun 2014 10:00:01 -0400 +Subject: mm: add !pte_present() check on existing hugetlb_entry callbacks + +From: Naoya Horiguchi + +commit d4c54919ed86302094c0ca7d48a8cbd4ee753e92 upstream. + +The age table walker doesn't check non-present hugetlb entry in common +path, so hugetlb_entry() callbacks must check it. The reason for this +behavior is that some callers want to handle it in its own way. + +[ I think that reason is bogus, btw - it should just do what the regular + code does, which is to call the "pte_hole()" function for such hugetlb + entries - Linus] + +However, some callers don't check it now, which causes unpredictable +result, for example when we have a race between migrating hugepage and +reading /proc/pid/numa_maps. This patch fixes it by adding !pte_present +checks on buggy callbacks. + +This bug exists for years and got visible by introducing hugepage +migration. + +ChangeLog v2: +- fix if condition (check !pte_present() instead of pte_present()) + +Reported-by: Sasha Levin +Signed-off-by: Naoya Horiguchi +Cc: Rik van Riel +Signed-off-by: Andrew Morton +[ Backported to 3.15. Signed-off-by: Josh Boyer ] +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/proc/task_mmu.c | 2 +- + mm/mempolicy.c | 6 +++++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -1350,7 +1350,7 @@ static int gather_hugetbl_stats(pte_t *p + struct numa_maps *md; + struct page *page; + +- if (pte_none(*pte)) ++ if (!pte_present(*pte)) + return 0; + + page = pte_page(*pte); +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -526,9 +526,13 @@ static void queue_pages_hugetlb_pmd_rang + int nid; + struct page *page; + spinlock_t *ptl; ++ pte_t entry; + + ptl = huge_pte_lock(hstate_vma(vma), vma->vm_mm, (pte_t *)pmd); +- page = pte_page(huge_ptep_get((pte_t *)pmd)); ++ entry = huge_ptep_get((pte_t *)pmd); ++ if (!pte_present(entry)) ++ goto unlock; ++ page = pte_page(entry); + nid = page_to_nid(page); + if (node_isset(nid, *nodes) == !!(flags & MPOL_MF_INVERT)) + goto unlock; diff --git a/queue-3.14/mm-rmap-fix-use-after-free-in-__put_anon_vma.patch b/queue-3.14/mm-rmap-fix-use-after-free-in-__put_anon_vma.patch new file mode 100644 index 00000000000..7cbf4c3f265 --- /dev/null +++ b/queue-3.14/mm-rmap-fix-use-after-free-in-__put_anon_vma.patch @@ -0,0 +1,42 @@ +From 624483f3ea82598ab0f62f1bdb9177f531ab1892 Mon Sep 17 00:00:00 2001 +From: Andrey Ryabinin +Date: Fri, 6 Jun 2014 19:09:30 +0400 +Subject: mm: rmap: fix use-after-free in __put_anon_vma + +From: Andrey Ryabinin + +commit 624483f3ea82598ab0f62f1bdb9177f531ab1892 upstream. + +While working address sanitizer for kernel I've discovered +use-after-free bug in __put_anon_vma. + +For the last anon_vma, anon_vma->root freed before child anon_vma. +Later in anon_vma_free(anon_vma) we are referencing to already freed +anon_vma->root to check rwsem. + +This fixes it by freeing the child anon_vma before freeing +anon_vma->root. + +Signed-off-by: Andrey Ryabinin +Acked-by: Peter Zijlstra +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/rmap.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -1554,10 +1554,9 @@ void __put_anon_vma(struct anon_vma *ano + { + struct anon_vma *root = anon_vma->root; + ++ anon_vma_free(anon_vma); + if (root != anon_vma && atomic_dec_and_test(&root->refcount)) + anon_vma_free(root); +- +- anon_vma_free(anon_vma); + } + + static struct anon_vma *rmap_walk_anon_lock(struct page *page, diff --git a/queue-3.14/series b/queue-3.14/series index 49ed1f6b1c5..c35f3c83afd 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -65,3 +65,8 @@ intel_pstate-remove-c0-tracking.patch intel_pstate-correct-rounding-in-busy-calculation.patch intel_pstate-add-sample-time-scaling.patch intel_pstate-improve-initial-busy-calculation.patch +mm-add-pte_present-check-on-existing-hugetlb_entry-callbacks.patch +mm-rmap-fix-use-after-free-in-__put_anon_vma.patch +iser-target-add-missing-target_put_sess_cmd-for-immedatedata-failure.patch +iscsi-target-fix-wrong-buffer-buffer-overrun-in-iscsi_change_param_value.patch +target-fix-alua_access_state-attribute-oops-for-un-configured-devices.patch diff --git a/queue-3.14/target-fix-alua_access_state-attribute-oops-for-un-configured-devices.patch b/queue-3.14/target-fix-alua_access_state-attribute-oops-for-un-configured-devices.patch new file mode 100644 index 00000000000..a5297cc5d16 --- /dev/null +++ b/queue-3.14/target-fix-alua_access_state-attribute-oops-for-un-configured-devices.patch @@ -0,0 +1,45 @@ +From f1453773514bb8b0bba0716301e8c8f17f8d39c7 Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Fri, 6 Jun 2014 00:52:57 -0700 +Subject: target: Fix alua_access_state attribute OOPs for un-configured devices + +From: Nicholas Bellinger + +commit f1453773514bb8b0bba0716301e8c8f17f8d39c7 upstream. + +This patch fixes a OOPs where an attempt to write to the per-device +alua_access_state configfs attribute at: + + /sys/kernel/config/target/core/$HBA/$DEV/alua/$TG_PT_GP/alua_access_state + +results in an NULL pointer dereference when the backend device has not +yet been configured. + +This patch adds an explicit check for DF_CONFIGURED, and fails with +-ENODEV to avoid this case. + +Reported-by: Chris Boot +Reported-by: Philip Gaw +Cc: Chris Boot +Cc: Philip Gaw +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/target_core_configfs.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/target/target_core_configfs.c ++++ b/drivers/target/target_core_configfs.c +@@ -2223,6 +2223,11 @@ static ssize_t target_core_alua_tg_pt_gp + " tg_pt_gp ID: %hu\n", tg_pt_gp->tg_pt_gp_valid_id); + return -EINVAL; + } ++ if (!(dev->dev_flags & DF_CONFIGURED)) { ++ pr_err("Unable to set alua_access_state while device is" ++ " not configured\n"); ++ return -ENODEV; ++ } + + ret = kstrtoul(page, 0, &tmp); + if (ret < 0) {