Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp2655129pxa; Mon, 17 Aug 2020 15:39:02 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzDDA1DZBUL7ZYJR8H19+jxLVCkUGGeLTR4dKdLggQIrqBlZ2Kgz/uAgV9u5scOjLYf7HPE X-Received: by 2002:a17:906:a84f:: with SMTP id dx15mr17137855ejb.377.1597703941868; Mon, 17 Aug 2020 15:39:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1597703941; cv=none; d=google.com; s=arc-20160816; b=hzkT2u4jnkuD5HTIR9HKCGoHdYAzyj5ZOeSzKDIfvPULaTboCbJLcGo0MJi6utu0pl hwCRV8oQnXw/bSLu7hb7VIz6Z7XbJFHq07E/D5AJOBxx6CZTcTLIx9Apnmn00Alau+pG atsIoy1Abf6yi/YSoMsrJuHcLglQtCgnEQ3YYDnJM5DWFJOtabMTLPNrywWhk3C/pFVQ xiEHitRQfaCzXBGbMQp6hp4DnZEewO5iWYQ3MiHc/lYHBpXzYeYUn8T5iGnQgWxsS3HP aegyMBD9SY5pCoiQJREbeJ8Pk8b9mL3EYrJfFxBevJnPK2C/4f+tlFEgbRyWQjTThtda O1pg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=f8VS7OwhsYDIW3oRUdhJ2et6GZkZYGX/IL2nX+UiWts=; b=ZFGaQBasSG6EDADdJAncre0HG+Ouxzpb4nYx65phJoIwyUfWdfFqG28NIOB7zTnBfS 7rw6+NudyrkqdIDzbMgcjYoG9HN6eaU1Jt0udLNZyP4FhVXPJ+3hK0y2XgkkzPfsVHw1 dhizNS00Od/giNBQq8RIRCWxwCSKrs+I+z/BJTbc68p8zXVV+sNMLl4JZh19++Pm6Q6M ZmCuDfDmGqKfJgFuJaAhjByVq0jgOa/PNPHNNrVT10MrGr6WjWPXGjGME1sW8mJFKtP5 whRyHlF4+CO8OQuzVR7cTxlRpabqBLAE0PpPgOaZDhiUy/+zYo9/omHjOT+mRLUXuUOJ sgjQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=eXRLfHoG; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id g22si11739289edm.555.2020.08.17.15.38.38; Mon, 17 Aug 2020 15:39:01 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=eXRLfHoG; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388004AbgHQRiE (ORCPT + 99 others); Mon, 17 Aug 2020 13:38:04 -0400 Received: from mail.kernel.org ([198.145.29.99]:56732 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731130AbgHQQRN (ORCPT ); Mon, 17 Aug 2020 12:17:13 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 1329A207D3; Mon, 17 Aug 2020 16:16:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1597681008; bh=298ivzhcBLRyRA38lYcnrq2YKbioF13wTBksvqrIRYs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eXRLfHoGLHxDZuZv1r4z7akOThCudtAzOTOKVpjMEn4H4V947ASh7GsUGur3XJy5/ IsgHOIXUZhn4l20+iGgH66w33fg+rlR15asAoWQUJHoCI4Kb8LjxcYGmqNeHkGt01C K8qHwxGLoj1VAH0qxINpD87s8Bm9DVXeGx9deLfg= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, John Allen , Tom Lendacky , Herbert Xu Subject: [PATCH 4.19 147/168] crypto: ccp - Fix use of merged scatterlists Date: Mon, 17 Aug 2020 17:17:58 +0200 Message-Id: <20200817143741.005610101@linuxfoundation.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200817143733.692105228@linuxfoundation.org> References: <20200817143733.692105228@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: John Allen commit 8a302808c60d441d9884cb00ea7f2b534f2e3ca5 upstream. Running the crypto manager self tests with CONFIG_CRYPTO_MANAGER_EXTRA_TESTS may result in several types of errors when using the ccp-crypto driver: alg: skcipher: cbc-des3-ccp encryption failed on test vector 0; expected_error=0, actual_error=-5 ... alg: skcipher: ctr-aes-ccp decryption overran dst buffer on test vector 0 ... alg: ahash: sha224-ccp test failed (wrong result) on test vector ... These errors are the result of improper processing of scatterlists mapped for DMA. Given a scatterlist in which entries are merged as part of mapping the scatterlist for DMA, the DMA length of a merged entry will reflect the combined length of the entries that were merged. The subsequent scatterlist entry will contain DMA information for the scatterlist entry after the last merged entry, but the non-DMA information will be that of the first merged entry. The ccp driver does not take this scatterlist merging into account. To address this, add a second scatterlist pointer to track the current position in the DMA mapped representation of the scatterlist. Both the DMA representation and the original representation of the scatterlist must be tracked as while most of the driver can use just the DMA representation, scatterlist_map_and_copy() must use the original representation and expects the scatterlist pointer to be accurate to the original representation. In order to properly walk the original scatterlist, the scatterlist must be walked until the combined lengths of the entries seen is equal to the DMA length of the current entry being processed in the DMA mapped representation. Fixes: 63b945091a070 ("crypto: ccp - CCP device driver and interface support") Signed-off-by: John Allen Cc: stable@vger.kernel.org Acked-by: Tom Lendacky Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/ccp/ccp-dev.h | 1 + drivers/crypto/ccp/ccp-ops.c | 37 ++++++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 11 deletions(-) --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -471,6 +471,7 @@ struct ccp_sg_workarea { unsigned int sg_used; struct scatterlist *dma_sg; + struct scatterlist *dma_sg_head; struct device *dma_dev; unsigned int dma_count; enum dma_data_direction dma_dir; --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c @@ -67,7 +67,7 @@ static u32 ccp_gen_jobid(struct ccp_devi static void ccp_sg_free(struct ccp_sg_workarea *wa) { if (wa->dma_count) - dma_unmap_sg(wa->dma_dev, wa->dma_sg, wa->nents, wa->dma_dir); + dma_unmap_sg(wa->dma_dev, wa->dma_sg_head, wa->nents, wa->dma_dir); wa->dma_count = 0; } @@ -96,6 +96,7 @@ static int ccp_init_sg_workarea(struct c return 0; wa->dma_sg = sg; + wa->dma_sg_head = sg; wa->dma_dev = dev; wa->dma_dir = dma_dir; wa->dma_count = dma_map_sg(dev, sg, wa->nents, dma_dir); @@ -108,14 +109,28 @@ static int ccp_init_sg_workarea(struct c static void ccp_update_sg_workarea(struct ccp_sg_workarea *wa, unsigned int len) { unsigned int nbytes = min_t(u64, len, wa->bytes_left); + unsigned int sg_combined_len = 0; if (!wa->sg) return; wa->sg_used += nbytes; wa->bytes_left -= nbytes; - if (wa->sg_used == wa->sg->length) { - wa->sg = sg_next(wa->sg); + if (wa->sg_used == sg_dma_len(wa->dma_sg)) { + /* Advance to the next DMA scatterlist entry */ + wa->dma_sg = sg_next(wa->dma_sg); + + /* In the case that the DMA mapped scatterlist has entries + * that have been merged, the non-DMA mapped scatterlist + * must be advanced multiple times for each merged entry. + * This ensures that the current non-DMA mapped entry + * corresponds to the current DMA mapped entry. + */ + do { + sg_combined_len += wa->sg->length; + wa->sg = sg_next(wa->sg); + } while (wa->sg_used > sg_combined_len); + wa->sg_used = 0; } } @@ -304,7 +319,7 @@ static unsigned int ccp_queue_buf(struct /* Update the structures and generate the count */ buf_count = 0; while (sg_wa->bytes_left && (buf_count < dm_wa->length)) { - nbytes = min(sg_wa->sg->length - sg_wa->sg_used, + nbytes = min(sg_dma_len(sg_wa->dma_sg) - sg_wa->sg_used, dm_wa->length - buf_count); nbytes = min_t(u64, sg_wa->bytes_left, nbytes); @@ -336,11 +351,11 @@ static void ccp_prepare_data(struct ccp_ * and destination. The resulting len values will always be <= UINT_MAX * because the dma length is an unsigned int. */ - sg_src_len = sg_dma_len(src->sg_wa.sg) - src->sg_wa.sg_used; + sg_src_len = sg_dma_len(src->sg_wa.dma_sg) - src->sg_wa.sg_used; sg_src_len = min_t(u64, src->sg_wa.bytes_left, sg_src_len); if (dst) { - sg_dst_len = sg_dma_len(dst->sg_wa.sg) - dst->sg_wa.sg_used; + sg_dst_len = sg_dma_len(dst->sg_wa.dma_sg) - dst->sg_wa.sg_used; sg_dst_len = min_t(u64, src->sg_wa.bytes_left, sg_dst_len); op_len = min(sg_src_len, sg_dst_len); } else { @@ -370,7 +385,7 @@ static void ccp_prepare_data(struct ccp_ /* Enough data in the sg element, but we need to * adjust for any previously copied data */ - op->src.u.dma.address = sg_dma_address(src->sg_wa.sg); + op->src.u.dma.address = sg_dma_address(src->sg_wa.dma_sg); op->src.u.dma.offset = src->sg_wa.sg_used; op->src.u.dma.length = op_len & ~(block_size - 1); @@ -391,7 +406,7 @@ static void ccp_prepare_data(struct ccp_ /* Enough room in the sg element, but we need to * adjust for any previously used area */ - op->dst.u.dma.address = sg_dma_address(dst->sg_wa.sg); + op->dst.u.dma.address = sg_dma_address(dst->sg_wa.dma_sg); op->dst.u.dma.offset = dst->sg_wa.sg_used; op->dst.u.dma.length = op->src.u.dma.length; } @@ -2034,7 +2049,7 @@ ccp_run_passthru_cmd(struct ccp_cmd_queu dst.sg_wa.sg_used = 0; for (i = 1; i <= src.sg_wa.dma_count; i++) { if (!dst.sg_wa.sg || - (dst.sg_wa.sg->length < src.sg_wa.sg->length)) { + (sg_dma_len(dst.sg_wa.sg) < sg_dma_len(src.sg_wa.sg))) { ret = -EINVAL; goto e_dst; } @@ -2060,8 +2075,8 @@ ccp_run_passthru_cmd(struct ccp_cmd_queu goto e_dst; } - dst.sg_wa.sg_used += src.sg_wa.sg->length; - if (dst.sg_wa.sg_used == dst.sg_wa.sg->length) { + dst.sg_wa.sg_used += sg_dma_len(src.sg_wa.sg); + if (dst.sg_wa.sg_used == sg_dma_len(dst.sg_wa.sg)) { dst.sg_wa.sg = sg_next(dst.sg_wa.sg); dst.sg_wa.sg_used = 0; }