From patchwork Fri Jan 30 08:12:27 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Nicholas A. Bellinger" X-Patchwork-Id: 5747831 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id BA4049F302 for ; Fri, 30 Jan 2015 08:46:00 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C3067201CE for ; Fri, 30 Jan 2015 08:45:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C2046201BB for ; Fri, 30 Jan 2015 08:45:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757862AbbA3Ipc (ORCPT ); Fri, 30 Jan 2015 03:45:32 -0500 Received: from mail-oi0-f50.google.com ([209.85.218.50]:34969 "EHLO mail-oi0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759748AbbA3Ipa (ORCPT ); Fri, 30 Jan 2015 03:45:30 -0500 Received: by mail-oi0-f50.google.com with SMTP id h136so33740568oig.9 for ; Fri, 30 Jan 2015 00:45:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tRGm2nadtjBP2/JtEjXztN0iRUeUG/a/k7Fx+DE7KKQ=; b=jIT9ZKKGxnKwQsV9vVubiLOb2V+RFmrBjJmsnEJjTBjjFPMNDL+OAppIhZl9VxVavk gTaqkk2a9/cFG1K4H66uZqIpndEjLypy1dQakfk24vtS4zS1voDL/nZytj/JxaCdzaAr 8YO7J4BpSDIxLMlWUbJsauUgpVi8893Y7CkrDy/eRY51rWALs6SKJnzpjDEw53lRgGkU pBc0UwmjQm3P/B9TY9ebK9NtUjOfXjF37HAUmX4K7dkcF4H9jhsIwdFhDD+PaN/RcU47 yT33kxVVsXxhc2jlUmeuHPYeBJzzRN1vRRy0CC3VdT8WpOrDmf33g2lTtyTdRHwQmZv2 lJEw== X-Gm-Message-State: ALoCoQmrVZ9D6vdxoz4UHhgkJ0T5tKBlVS8hW+jqqEGLyLYESuLzc5/Sakzc6S6V+fm7rmDp+Zej X-Received: by 10.202.85.146 with SMTP id j140mr2908916oib.65.1422607529972; Fri, 30 Jan 2015 00:45:29 -0800 (PST) Received: from localhost.localdomain (mail.linux-iscsi.org. [67.23.28.174]) by mx.google.com with ESMTPSA id l3sm5046132obx.14.2015.01.30.00.45.29 (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 30 Jan 2015 00:45:29 -0800 (PST) From: "Nicholas A. Bellinger" To: target-devel Cc: linux-scsi , kvm-devel , Paolo Bonzini , "Michael S. Tsirkin" , Nicholas Bellinger Subject: [PATCH 3/8] vhost/scsi: Fix incorrect early vhost_scsi_handle_vq failures Date: Fri, 30 Jan 2015 08:12:27 +0000 Message-Id: <1422605552-24797-4-git-send-email-nab@daterainc.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1422605552-24797-1-git-send-email-nab@daterainc.com> References: <1422605552-24797-1-git-send-email-nab@daterainc.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Nicholas Bellinger This patch fixes vhost_scsi_handle_vq() failure cases that result in BUG_ON() getting triggered when vhost_scsi_free_cmd() is called, and ->tvc_se_cmd has not been initialized by target_submit_cmd_map_sgls(). It changes tcm_vhost_release_cmd() to use tcm_vhost_cmd->tvc_nexus for obtaining se_session pointer reference. Also, avoid calling put_page() on NULL sg->page entries in vhost_scsi_map_to_sgl() failure path. Cc: Michael S. Tsirkin Cc: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/vhost/scsi.c | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index a03ac41..9c5ac23 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -460,7 +460,7 @@ static void tcm_vhost_release_cmd(struct se_cmd *se_cmd) { struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd, struct tcm_vhost_cmd, tvc_se_cmd); - struct se_session *se_sess = se_cmd->se_sess; + struct se_session *se_sess = tv_cmd->tvc_nexus->tvn_se_sess; int i; if (tv_cmd->tvc_sgl_count) { @@ -859,9 +859,11 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd, ret = vhost_scsi_map_to_sgl(cmd, sg, sgl_count, &iov[i], cmd->tvc_upages, write); if (ret < 0) { - for (i = 0; i < cmd->tvc_sgl_count; i++) - put_page(sg_page(&cmd->tvc_sgl[i])); - + for (i = 0; i < cmd->tvc_sgl_count; i++) { + struct page *page = sg_page(&cmd->tvc_sgl[i]); + if (page) + put_page(page); + } cmd->tvc_sgl_count = 0; return ret; } @@ -900,9 +902,11 @@ vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd, ret = vhost_scsi_map_to_sgl(cmd, prot_sg, prot_sgl_count, &iov[i], cmd->tvc_upages, write); if (ret < 0) { - for (i = 0; i < cmd->tvc_prot_sgl_count; i++) - put_page(sg_page(&cmd->tvc_prot_sgl[i])); - + for (i = 0; i < cmd->tvc_prot_sgl_count; i++) { + struct page *page = sg_page(&cmd->tvc_prot_sgl[i]); + if (page) + put_page(page); + } cmd->tvc_prot_sgl_count = 0; return ret; } @@ -1060,12 +1064,14 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) if (unlikely(vq->iov[0].iov_len < req_size)) { pr_err("Expecting virtio-scsi header: %zu, got %zu\n", req_size, vq->iov[0].iov_len); - break; + vhost_scsi_send_bad_target(vs, vq, head, out); + continue; } ret = memcpy_fromiovecend(req, &vq->iov[0], 0, req_size); if (unlikely(ret)) { vq_err(vq, "Faulted on virtio_scsi_cmd_req\n"); - break; + vhost_scsi_send_bad_target(vs, vq, head, out); + continue; } /* virtio-scsi spec requires byte 0 of the lun to be 1 */ @@ -1096,14 +1102,16 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) if (data_direction != DMA_TO_DEVICE) { vq_err(vq, "Received non zero do_pi_niov" ", but wrong data_direction\n"); - goto err_cmd; + vhost_scsi_send_bad_target(vs, vq, head, out); + continue; } prot_bytes = vhost32_to_cpu(vq, v_req_pi.pi_bytesout); } else if (v_req_pi.pi_bytesin) { if (data_direction != DMA_FROM_DEVICE) { vq_err(vq, "Received non zero di_pi_niov" ", but wrong data_direction\n"); - goto err_cmd; + vhost_scsi_send_bad_target(vs, vq, head, out); + continue; } prot_bytes = vhost32_to_cpu(vq, v_req_pi.pi_bytesin); } @@ -1143,7 +1151,8 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) vq_err(vq, "Received SCSI CDB with command_size: %d that" " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", scsi_command_size(cdb), TCM_VHOST_MAX_CDB_SIZE); - goto err_cmd; + vhost_scsi_send_bad_target(vs, vq, head, out); + continue; } cmd = vhost_scsi_get_tag(vq, tpg, cdb, tag, lun, task_attr, @@ -1152,7 +1161,8 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) if (IS_ERR(cmd)) { vq_err(vq, "vhost_scsi_get_tag failed %ld\n", PTR_ERR(cmd)); - goto err_cmd; + vhost_scsi_send_bad_target(vs, vq, head, out); + continue; } pr_debug("Allocated tv_cmd: %p exp_data_len: %d, data_direction" @@ -1172,7 +1182,9 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) if (unlikely(ret)) { vq_err(vq, "Failed to map iov to" " prot_sgl\n"); - goto err_free; + tcm_vhost_release_cmd(&cmd->tvc_se_cmd); + vhost_scsi_send_bad_target(vs, vq, head, out); + continue; } } if (data_direction != DMA_NONE) { @@ -1181,7 +1193,9 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) data_direction == DMA_FROM_DEVICE); if (unlikely(ret)) { vq_err(vq, "Failed to map iov to sgl\n"); - goto err_free; + tcm_vhost_release_cmd(&cmd->tvc_se_cmd); + vhost_scsi_send_bad_target(vs, vq, head, out); + continue; } } /* @@ -1199,14 +1213,6 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) INIT_WORK(&cmd->work, tcm_vhost_submission_work); queue_work(tcm_vhost_workqueue, &cmd->work); } - - mutex_unlock(&vq->mutex); - return; - -err_free: - vhost_scsi_free_cmd(cmd); -err_cmd: - vhost_scsi_send_bad_target(vs, vq, head, out); out: mutex_unlock(&vq->mutex); }