diff mbox series

[1/2] crypto: mxs-dcp: Check for DMA mapping errors

Message ID 20210618211411.1167726-1-sean.anderson@seco.com
State Accepted
Commit df6313d707e575a679ada3313358289af24454c0
Headers show
Series [1/2] crypto: mxs-dcp: Check for DMA mapping errors | expand

Commit Message

Sean Anderson June 18, 2021, 9:14 p.m. UTC
After calling dma_map_single(), we must also call dma_mapping_error().
This fixes the following warning when compiling with CONFIG_DMA_API_DEBUG:

[  311.241478] WARNING: CPU: 0 PID: 428 at kernel/dma/debug.c:1027 check_unmap+0x79c/0x96c
[  311.249547] DMA-API: mxs-dcp 2280000.crypto: device driver failed to check map error[device address=0x00000000860cb080] [size=32 bytes] [mapped as single]

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/crypto/mxs-dcp.c | 45 +++++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 10 deletions(-)

Comments

Herbert Xu June 24, 2021, 6:56 a.m. UTC | #1
On Fri, Jun 18, 2021 at 05:14:11PM -0400, Sean Anderson wrote:
> This uses the sg_miter_*() functions to copy data, instead of doing it

> ourselves. Using sg_copy_buffer() would be better, but this way we don't

> have to keep traversing the beginning of the scatterlist every time we

> do another copy.

> 

> In addition to reducing code size, this fixes the following oops

> resulting from failing to kmap the page:


Thanks for the patch.  Just a minor nit:

> @@ -365,25 +364,13 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)

>  

>  				out_tmp = out_buf;

>  				last_out_len = actx->fill;

> -				while (dst && actx->fill) {

> -					if (!split) {

> -						dst_buf = sg_virt(dst);

> -						dst_off = 0;

> -					}

> -					rem = min(sg_dma_len(dst) - dst_off,

> -						  actx->fill);

> -

> -					memcpy(dst_buf + dst_off, out_tmp, rem);

> +

> +				while (sg_miter_next(&dst_iter) && actx->fill) {

> +					rem = min(dst_iter.length, actx->fill);


This comparison generates a sparse warning due to conflicting types,
please fix this and resubmit.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Sean Anderson June 24, 2021, 2:58 p.m. UTC | #2
On 6/24/21 2:56 AM, Herbert Xu wrote:
 > On Fri, Jun 18, 2021 at 05:14:11PM -0400, Sean Anderson wrote:

 >> This uses the sg_miter_*() functions to copy data, instead of doing it

 >> ourselves. Using sg_copy_buffer() would be better, but this way we don't

 >> have to keep traversing the beginning of the scatterlist every time we

 >> do another copy.

 >>

 >> In addition to reducing code size, this fixes the following oops

 >> resulting from failing to kmap the page:

 >

 > Thanks for the patch.  Just a minor nit:

 >

 >> @@ -365,25 +364,13 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)

 >>

 >>  				out_tmp = out_buf;

 >>  				last_out_len = actx->fill;

 >> -				while (dst && actx->fill) {

 >> -					if (!split) {

 >> -						dst_buf = sg_virt(dst);

 >> -						dst_off = 0;

 >> -					}

 >> -					rem = min(sg_dma_len(dst) - dst_off,

 >> -						  actx->fill);

 >> -

 >> -					memcpy(dst_buf + dst_off, out_tmp, rem);

 >> +

 >> +				while (sg_miter_next(&dst_iter) && actx->fill) {

 >> +					rem = min(dst_iter.length, actx->fill);

 >

 > This comparison generates a sparse warning due to conflicting types,

 > please fix this and resubmit.


What exactly is the warning here? dst_iter.length is a size_t, and
actx->fill is a u32. So fill will be converted to a size_t before the
comparison, which is lossless.

--Sean
Herbert Xu June 25, 2021, 12:16 a.m. UTC | #3
On Thu, Jun 24, 2021 at 10:58:48AM -0400, Sean Anderson wrote:
>

> What exactly is the warning here? dst_iter.length is a size_t, and

> actx->fill is a u32. So fill will be converted to a size_t before the

> comparison, which is lossless.


It's just the way min works.  If you want to shut it up, you can
either use a cast or min_t.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Sean Anderson June 25, 2021, 2:49 p.m. UTC | #4
On 6/24/21 8:16 PM, Herbert Xu wrote:
> On Thu, Jun 24, 2021 at 10:58:48AM -0400, Sean Anderson wrote:

>>

>> What exactly is the warning here? dst_iter.length is a size_t, and

>> actx->fill is a u32. So fill will be converted to a size_t before the

>> comparison, which is lossless.

> 

> It's just the way min works.  If you want to shut it up, you can

> either use a cast or min_t.


What version of sparse are you using? With sparse 0.6.2, gcc 9.3.0, and
with C=1 and W=2 I don't see this warning.

--Sean
Herbert Xu June 26, 2021, 3 a.m. UTC | #5
On Fri, Jun 25, 2021 at 10:49:08AM -0400, Sean Anderson wrote:
>

> What version of sparse are you using? With sparse 0.6.2, gcc 9.3.0, and

> with C=1 and W=2 I don't see this warning.


Oh it could be my sparse being out-of-date, I'll get it another go.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Herbert Xu June 28, 2021, 3:25 a.m. UTC | #6
On Fri, Jun 25, 2021 at 10:49:08AM -0400, Sean Anderson wrote:
>

> What version of sparse are you using? With sparse 0.6.2, gcc 9.3.0, and

> with C=1 and W=2 I don't see this warning.


OK I've upgraded my sparse to the latest git tree, but it still
gives the same warning, because the two types are of different
sizes:

$ make C=1 W=1 O=build-compile drivers/crypto/
make[1]: Entering directory '/home/herbert/src/build/kernel/test/build-compile'
  GEN     Makefile
  CALL    ../scripts/checksyscalls.sh
  CALL    ../scripts/atomic/check-atomics.sh
  CC [M]  drivers/crypto/mxs-dcp.o
In file included from ../include/linux/kernel.h:15,
                 from ../arch/x86/include/asm/percpu.h:27,
                 from ../arch/x86/include/asm/current.h:6,
                 from ../include/linux/sched.h:12,
                 from ../include/linux/ratelimit.h:6,
                 from ../include/linux/dev_printk.h:16,
                 from ../include/linux/device.h:15,
                 from ../include/linux/dma-mapping.h:7,
                 from ../drivers/crypto/mxs-dcp.c:8:
../drivers/crypto/mxs-dcp.c: In function \u2018mxs_dcp_aes_block_crypt\u2019:
../include/linux/minmax.h:18:28: warning: comparison of distinct pointer types lacks a cast
  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
                            ^~
../include/linux/minmax.h:32:4: note: in expansion of macro \u2018__typecheck\u2019
   (__typecheck(x, y) && __no_side_effects(x, y))
    ^~~~~~~~~~~
../include/linux/minmax.h:42:24: note: in expansion of macro \u2018__safe_cmp\u2019
  __builtin_choose_expr(__safe_cmp(x, y), \
                        ^~~~~~~~~~
../include/linux/minmax.h:51:19: note: in expansion of macro \u2018__careful_cmp\u2019
 #define min(x, y) __careful_cmp(x, y, <)
                   ^~~~~~~~~~~~~
../drivers/crypto/mxs-dcp.c:369:12: note: in expansion of macro \u2018min\u2019
      rem = min(dst_iter.length, actx->fill);
            ^~~
  CHECK   ../drivers/crypto/mxs-dcp.c
../drivers/crypto/mxs-dcp.c:369:47: error: incompatible types in comparison expression (different type sizes):
../drivers/crypto/mxs-dcp.c:369:47:    unsigned long *
../drivers/crypto/mxs-dcp.c:369:47:    unsigned int *
make[1]: Leaving directory '/home/herbert/src/build/kernel/test/build-compile'
$ 

In fact as you can see that gcc is warning too.  Perhaps you're
building on 32-bit?

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Sean Anderson June 28, 2021, 5:44 p.m. UTC | #7
On 6/27/21 11:25 PM, Herbert Xu wrote:
> On Fri, Jun 25, 2021 at 10:49:08AM -0400, Sean Anderson wrote:

>>

>> What version of sparse are you using? With sparse 0.6.2, gcc 9.3.0, and

>> with C=1 and W=2 I don't see this warning.

>

> OK I've upgraded my sparse to the latest git tree, but it still

> gives the same warning, because the two types are of different

> sizes:

>

> $ make C=1 W=1 O=build-compile drivers/crypto/

> make[1]: Entering directory '/home/herbert/src/build/kernel/test/build-compile'

>    GEN     Makefile

>    CALL    ../scripts/checksyscalls.sh

>    CALL    ../scripts/atomic/check-atomics.sh

>    CC [M]  drivers/crypto/mxs-dcp.o

> In file included from ../include/linux/kernel.h:15,

>                   from ../arch/x86/include/asm/percpu.h:27,

>                   from ../arch/x86/include/asm/current.h:6,

>                   from ../include/linux/sched.h:12,

>                   from ../include/linux/ratelimit.h:6,

>                   from ../include/linux/dev_printk.h:16,

>                   from ../include/linux/device.h:15,

>                   from ../include/linux/dma-mapping.h:7,

>                   from ../drivers/crypto/mxs-dcp.c:8:

> ../drivers/crypto/mxs-dcp.c: In function \u2018mxs_dcp_aes_block_crypt\u2019:

> ../include/linux/minmax.h:18:28: warning: comparison of distinct pointer types lacks a cast

>    (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))

>                              ^~

> ../include/linux/minmax.h:32:4: note: in expansion of macro \u2018__typecheck\u2019

>     (__typecheck(x, y) && __no_side_effects(x, y))

>      ^~~~~~~~~~~

> ../include/linux/minmax.h:42:24: note: in expansion of macro \u2018__safe_cmp\u2019

>    __builtin_choose_expr(__safe_cmp(x, y), \

>                          ^~~~~~~~~~

> ../include/linux/minmax.h:51:19: note: in expansion of macro \u2018__careful_cmp\u2019

>   #define min(x, y) __careful_cmp(x, y, <)

>                     ^~~~~~~~~~~~~

> ../drivers/crypto/mxs-dcp.c:369:12: note: in expansion of macro \u2018min\u2019

>        rem = min(dst_iter.length, actx->fill);

>              ^~~

>    CHECK   ../drivers/crypto/mxs-dcp.c

> ../drivers/crypto/mxs-dcp.c:369:47: error: incompatible types in comparison expression (different type sizes):

> ../drivers/crypto/mxs-dcp.c:369:47:    unsigned long *

> ../drivers/crypto/mxs-dcp.c:369:47:    unsigned int *

> make[1]: Leaving directory '/home/herbert/src/build/kernel/test/build-compile'

> $

>

> In fact as you can see that gcc is warning too.  Perhaps you're

> building on 32-bit?


Ah, that would be it. Although this module depends on ARCH_MXS ||
ARCH_MXC and does not (yet) have COMPILE_TEST as an option, so I wonder
how you ran into this :)

Either way, I will send a v2 with this fixed.

>

> Thanks,

>
diff mbox series

Patch

diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c
index d6a7784d2988..f397cc5bf102 100644
--- a/drivers/crypto/mxs-dcp.c
+++ b/drivers/crypto/mxs-dcp.c
@@ -170,15 +170,19 @@  static struct dcp *global_sdcp;
 
 static int mxs_dcp_start_dma(struct dcp_async_ctx *actx)
 {
+	int dma_err;
 	struct dcp *sdcp = global_sdcp;
 	const int chan = actx->chan;
 	uint32_t stat;
 	unsigned long ret;
 	struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
-
 	dma_addr_t desc_phys = dma_map_single(sdcp->dev, desc, sizeof(*desc),
 					      DMA_TO_DEVICE);
 
+	dma_err = dma_mapping_error(sdcp->dev, desc_phys);
+	if (dma_err)
+		return dma_err;
+
 	reinit_completion(&sdcp->completion[chan]);
 
 	/* Clear status register. */
@@ -216,18 +220,29 @@  static int mxs_dcp_start_dma(struct dcp_async_ctx *actx)
 static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
 			   struct skcipher_request *req, int init)
 {
+	dma_addr_t key_phys, src_phys, dst_phys;
 	struct dcp *sdcp = global_sdcp;
 	struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
 	struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req);
 	int ret;
 
-	dma_addr_t key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key,
-					     2 * AES_KEYSIZE_128,
-					     DMA_TO_DEVICE);
-	dma_addr_t src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf,
-					     DCP_BUF_SZ, DMA_TO_DEVICE);
-	dma_addr_t dst_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_out_buf,
-					     DCP_BUF_SZ, DMA_FROM_DEVICE);
+	key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key,
+				  2 * AES_KEYSIZE_128, DMA_TO_DEVICE);
+	ret = dma_mapping_error(sdcp->dev, key_phys);
+	if (ret)
+		return ret;
+
+	src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf,
+				  DCP_BUF_SZ, DMA_TO_DEVICE);
+	ret = dma_mapping_error(sdcp->dev, src_phys);
+	if (ret)
+		goto err_src;
+
+	dst_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_out_buf,
+				  DCP_BUF_SZ, DMA_FROM_DEVICE);
+	ret = dma_mapping_error(sdcp->dev, dst_phys);
+	if (ret)
+		goto err_dst;
 
 	if (actx->fill % AES_BLOCK_SIZE) {
 		dev_err(sdcp->dev, "Invalid block size!\n");
@@ -265,10 +280,12 @@  static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
 	ret = mxs_dcp_start_dma(actx);
 
 aes_done_run:
+	dma_unmap_single(sdcp->dev, dst_phys, DCP_BUF_SZ, DMA_FROM_DEVICE);
+err_dst:
+	dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
+err_src:
 	dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128,
 			 DMA_TO_DEVICE);
-	dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
-	dma_unmap_single(sdcp->dev, dst_phys, DCP_BUF_SZ, DMA_FROM_DEVICE);
 
 	return ret;
 }
@@ -557,6 +574,10 @@  static int mxs_dcp_run_sha(struct ahash_request *req)
 	dma_addr_t buf_phys = dma_map_single(sdcp->dev, sdcp->coh->sha_in_buf,
 					     DCP_BUF_SZ, DMA_TO_DEVICE);
 
+	ret = dma_mapping_error(sdcp->dev, buf_phys);
+	if (ret)
+		return ret;
+
 	/* Fill in the DMA descriptor. */
 	desc->control0 = MXS_DCP_CONTROL0_DECR_SEMAPHORE |
 		    MXS_DCP_CONTROL0_INTERRUPT |
@@ -589,6 +610,10 @@  static int mxs_dcp_run_sha(struct ahash_request *req)
 	if (rctx->fini) {
 		digest_phys = dma_map_single(sdcp->dev, sdcp->coh->sha_out_buf,
 					     DCP_SHA_PAY_SZ, DMA_FROM_DEVICE);
+		ret = dma_mapping_error(sdcp->dev, digest_phys);
+		if (ret)
+			goto done_run;
+
 		desc->control0 |= MXS_DCP_CONTROL0_HASH_TERM;
 		desc->payload = digest_phys;
 	}