Skip to content

Commit b548493

Browse files
committed
Merge branch 'chcr-Fixing-issues-in-dma-mapping-and-driver-removal'
Ayush Sawal says: ==================== Fixing issues in dma mapping and driver removal Patch 1: This fixes the kernel panic which occurs due to the accessing of a zero length sg. Patch 2: Avoiding unregistering the algorithm if cra_refcnt is not 1. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 934e36e + 8b9914c commit b548493

File tree

1 file changed

+59
-22
lines changed

1 file changed

+59
-22
lines changed

drivers/crypto/chelsio/chcr_algo.c

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,11 +2590,22 @@ int chcr_aead_dma_map(struct device *dev,
25902590
struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
25912591
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
25922592
unsigned int authsize = crypto_aead_authsize(tfm);
2593-
int dst_size;
2593+
int src_len, dst_len;
25942594

2595-
dst_size = req->assoclen + req->cryptlen + (op_type ?
2596-
0 : authsize);
2597-
if (!req->cryptlen || !dst_size)
2595+
/* calculate and handle src and dst sg length separately
2596+
* for inplace and out-of place operations
2597+
*/
2598+
if (req->src == req->dst) {
2599+
src_len = req->assoclen + req->cryptlen + (op_type ?
2600+
0 : authsize);
2601+
dst_len = src_len;
2602+
} else {
2603+
src_len = req->assoclen + req->cryptlen;
2604+
dst_len = req->assoclen + req->cryptlen + (op_type ?
2605+
-authsize : authsize);
2606+
}
2607+
2608+
if (!req->cryptlen || !src_len || !dst_len)
25982609
return 0;
25992610
reqctx->iv_dma = dma_map_single(dev, reqctx->iv, (IV + reqctx->b0_len),
26002611
DMA_BIDIRECTIONAL);
@@ -2606,20 +2617,23 @@ int chcr_aead_dma_map(struct device *dev,
26062617
reqctx->b0_dma = 0;
26072618
if (req->src == req->dst) {
26082619
error = dma_map_sg(dev, req->src,
2609-
sg_nents_for_len(req->src, dst_size),
2620+
sg_nents_for_len(req->src, src_len),
26102621
DMA_BIDIRECTIONAL);
26112622
if (!error)
26122623
goto err;
26132624
} else {
2614-
error = dma_map_sg(dev, req->src, sg_nents(req->src),
2625+
error = dma_map_sg(dev, req->src,
2626+
sg_nents_for_len(req->src, src_len),
26152627
DMA_TO_DEVICE);
26162628
if (!error)
26172629
goto err;
2618-
error = dma_map_sg(dev, req->dst, sg_nents(req->dst),
2630+
error = dma_map_sg(dev, req->dst,
2631+
sg_nents_for_len(req->dst, dst_len),
26192632
DMA_FROM_DEVICE);
26202633
if (!error) {
2621-
dma_unmap_sg(dev, req->src, sg_nents(req->src),
2622-
DMA_TO_DEVICE);
2634+
dma_unmap_sg(dev, req->src,
2635+
sg_nents_for_len(req->src, src_len),
2636+
DMA_TO_DEVICE);
26232637
goto err;
26242638
}
26252639
}
@@ -2637,24 +2651,37 @@ void chcr_aead_dma_unmap(struct device *dev,
26372651
struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
26382652
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
26392653
unsigned int authsize = crypto_aead_authsize(tfm);
2640-
int dst_size;
2654+
int src_len, dst_len;
26412655

2642-
dst_size = req->assoclen + req->cryptlen + (op_type ?
2643-
0 : authsize);
2644-
if (!req->cryptlen || !dst_size)
2656+
/* calculate and handle src and dst sg length separately
2657+
* for inplace and out-of place operations
2658+
*/
2659+
if (req->src == req->dst) {
2660+
src_len = req->assoclen + req->cryptlen + (op_type ?
2661+
0 : authsize);
2662+
dst_len = src_len;
2663+
} else {
2664+
src_len = req->assoclen + req->cryptlen;
2665+
dst_len = req->assoclen + req->cryptlen + (op_type ?
2666+
-authsize : authsize);
2667+
}
2668+
2669+
if (!req->cryptlen || !src_len || !dst_len)
26452670
return;
26462671

26472672
dma_unmap_single(dev, reqctx->iv_dma, (IV + reqctx->b0_len),
26482673
DMA_BIDIRECTIONAL);
26492674
if (req->src == req->dst) {
26502675
dma_unmap_sg(dev, req->src,
2651-
sg_nents_for_len(req->src, dst_size),
2676+
sg_nents_for_len(req->src, src_len),
26522677
DMA_BIDIRECTIONAL);
26532678
} else {
2654-
dma_unmap_sg(dev, req->src, sg_nents(req->src),
2655-
DMA_TO_DEVICE);
2656-
dma_unmap_sg(dev, req->dst, sg_nents(req->dst),
2657-
DMA_FROM_DEVICE);
2679+
dma_unmap_sg(dev, req->src,
2680+
sg_nents_for_len(req->src, src_len),
2681+
DMA_TO_DEVICE);
2682+
dma_unmap_sg(dev, req->dst,
2683+
sg_nents_for_len(req->dst, dst_len),
2684+
DMA_FROM_DEVICE);
26582685
}
26592686
}
26602687

@@ -4364,22 +4391,32 @@ static int chcr_unregister_alg(void)
43644391
for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
43654392
switch (driver_algs[i].type & CRYPTO_ALG_TYPE_MASK) {
43664393
case CRYPTO_ALG_TYPE_SKCIPHER:
4367-
if (driver_algs[i].is_registered)
4394+
if (driver_algs[i].is_registered && refcount_read(
4395+
&driver_algs[i].alg.skcipher.base.cra_refcnt)
4396+
== 1) {
43684397
crypto_unregister_skcipher(
43694398
&driver_algs[i].alg.skcipher);
4399+
driver_algs[i].is_registered = 0;
4400+
}
43704401
break;
43714402
case CRYPTO_ALG_TYPE_AEAD:
4372-
if (driver_algs[i].is_registered)
4403+
if (driver_algs[i].is_registered && refcount_read(
4404+
&driver_algs[i].alg.aead.base.cra_refcnt) == 1) {
43734405
crypto_unregister_aead(
43744406
&driver_algs[i].alg.aead);
4407+
driver_algs[i].is_registered = 0;
4408+
}
43754409
break;
43764410
case CRYPTO_ALG_TYPE_AHASH:
4377-
if (driver_algs[i].is_registered)
4411+
if (driver_algs[i].is_registered && refcount_read(
4412+
&driver_algs[i].alg.hash.halg.base.cra_refcnt)
4413+
== 1) {
43784414
crypto_unregister_ahash(
43794415
&driver_algs[i].alg.hash);
4416+
driver_algs[i].is_registered = 0;
4417+
}
43804418
break;
43814419
}
4382-
driver_algs[i].is_registered = 0;
43834420
}
43844421
return 0;
43854422
}

0 commit comments

Comments
 (0)