Skip to content

Commit fb90a1c

Browse files
ayushsawldavem330
authored andcommitted
Crypto/chcr: Calculate src and dst sg lengths separately for dma map
This patch calculates src and dst sg lengths separately for dma mapping in case of aead operation. This fixes a panic which occurs due to the accessing of a zero length sg. Panic: [ 138.173225] kernel BUG at drivers/iommu/intel-iommu.c:1184! Signed-off-by: Ayush Sawal <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 934e36e commit fb90a1c

File tree

1 file changed

+45
-18
lines changed

1 file changed

+45
-18
lines changed

drivers/crypto/chelsio/chcr_algo.c

Lines changed: 45 additions & 18 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

0 commit comments

Comments
 (0)