From patchwork Fri Aug 3 08:48:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maurizio Lombardi X-Patchwork-Id: 10554769 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C190E139A for ; Fri, 3 Aug 2018 08:48:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AD2152C0E2 for ; Fri, 3 Aug 2018 08:48:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A03432C0E7; Fri, 3 Aug 2018 08:48:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2C7862BE3C for ; Fri, 3 Aug 2018 08:48:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731119AbeHCKnV (ORCPT ); Fri, 3 Aug 2018 06:43:21 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:51016 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1730129AbeHCKnV (ORCPT ); Fri, 3 Aug 2018 06:43:21 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 027C84015A58; Fri, 3 Aug 2018 08:48:03 +0000 (UTC) Received: from manaslu.redhat.com (unknown [10.33.36.17]) by smtp.corp.redhat.com (Postfix) with ESMTP id 01E8721CB507; Fri, 3 Aug 2018 08:48:01 +0000 (UTC) From: Maurizio Lombardi To: target-devel@vger.kernel.org Cc: linux-scsi@vger.kernel.org, nab@linux-iscsi.org Subject: [PATCH RESEND v2] target: move the rx hdr buffer out of the stack Date: Fri, 3 Aug 2018 10:48:00 +0200 Message-Id: <1533286080-13099-1-git-send-email-mlombard@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Fri, 03 Aug 2018 08:48:03 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Fri, 03 Aug 2018 08:48:03 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'mlombard@redhat.com' RCPT:'' Sender: target-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: target-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When HeaderDigest is enabled on aarch64 machines, target triggers a lot of failed crc checksum errors: example of output in dmesg: [ 154.495031] HeaderDigest CRC32C failed, received 0x60571c8d, computed 0x288c3ab9 [ 154.583821] Got unknown iSCSI OpCode: 0xff [ 162.979857] HeaderDigest CRC32C failed, received 0x0712e57c, computed 0x288c3ab9 ... The problem is that the iscsit_get_rx_pdu() function uses a stack buffer as input for the scatterlist crypto library. This should be avoided on kernels >= 4.9 because stack buffers may not be directly mappable to struct page when the CONFIG_VMAP_STACK option is enabled. This patch modifies the code so the buffer will be allocated on the heap and adds a pointer to it in the iscsi_conn structure. v2: allocate conn_rx_buf in iscsi_target_login_thread() and fix a memory leak Signed-off-by: Maurizio Lombardi --- drivers/target/iscsi/iscsi_target.c | 6 +++++- drivers/target/iscsi/iscsi_target_login.c | 15 +++++++++++++++ include/target/iscsi/iscsi_target_core.h | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 8e22379..149fa91 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3913,10 +3913,12 @@ static bool iscsi_target_check_conn_state(struct iscsi_conn *conn) static void iscsit_get_rx_pdu(struct iscsi_conn *conn) { int ret; - u8 buffer[ISCSI_HDR_LEN], opcode; + u8 *buffer, opcode; u32 checksum = 0, digest = 0; struct kvec iov; + buffer = conn->conn_rx_buf; + while (!kthread_should_stop()) { /* * Ensure that both TX and RX per connection kthreads @@ -4211,6 +4213,8 @@ int iscsit_close_connection( crypto_free_ahash(tfm); } + kfree(conn->conn_rx_buf); + free_cpumask_var(conn->conn_cpumask); kfree(conn->conn_ops); diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 9950178..4e8974a5 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -1203,6 +1203,8 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn, crypto_free_ahash(tfm); } + kfree(conn->conn_rx_buf); + free_cpumask_var(conn->conn_cpumask); kfree(conn->conn_ops); @@ -1262,6 +1264,15 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) /* Get another socket */ return 1; } + + /* Allocate buffer for iscsit_get_rx_pdu() */ + conn->conn_rx_buf = kmalloc(ISCSI_HDR_LEN, GFP_KERNEL); + if (!conn->conn_rx_buf) { + pr_err("Could not allocate memory for conn_rx_buf\n"); + kfree(conn); + return 1; + } + pr_debug("Moving to TARG_CONN_STATE_FREE.\n"); conn->conn_state = TARG_CONN_STATE_FREE; @@ -1270,6 +1281,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0); if (iscsit_conn_set_transport(conn, np->np_transport) < 0) { + kfree(conn->conn_rx_buf); kfree(conn); return 1; } @@ -1278,6 +1290,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) if (rc == -ENOSYS) { complete(&np->np_restart_comp); iscsit_put_transport(conn->conn_transport); + kfree(conn->conn_rx_buf); kfree(conn); conn = NULL; goto exit; @@ -1288,6 +1301,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) spin_unlock_bh(&np->np_thread_lock); complete(&np->np_restart_comp); iscsit_put_transport(conn->conn_transport); + kfree(conn->conn_rx_buf); kfree(conn); conn = NULL; /* Get another socket */ @@ -1295,6 +1309,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) } spin_unlock_bh(&np->np_thread_lock); iscsit_put_transport(conn->conn_transport); + kfree(conn->conn_rx_buf); kfree(conn); conn = NULL; goto out; diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index cf5f3ff..3e9c525 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -584,6 +584,8 @@ struct iscsi_conn { /* libcrypto RX and TX contexts for crc32c */ struct ahash_request *conn_rx_hash; struct ahash_request *conn_tx_hash; + /* Used as buffer for iscsit_get_rx_pdu */ + u8 *conn_rx_buf; /* Used for scheduling TX and RX connection kthreads */ cpumask_var_t conn_cpumask; unsigned int conn_rx_reset_cpumask:1;