Skip to content

Commit 660ca94

Browse files
committed
crypto: caam - Fix edesc/iv ordering mixup
The attempt to add DMA alignment padding by moving IV to the front of edesc was completely broken as it didn't change the places where edesc was freed. It's also wrong as the IV may still share a cache-line with the edesc. Fix this by restoring the original layout and simply reserving enough memmory so that the IV is on a DMA cache-line by itself. Reported-by: Meenakshi Aggarwal <[email protected]> Fixes: 199354d ("crypto: caam - Remove GFP_DMA and add DMA alignment padding") Signed-off-by: Herbert Xu <[email protected]>
1 parent 8b84475 commit 660ca94

File tree

3 files changed

+53
-23
lines changed

3 files changed

+53
-23
lines changed

drivers/crypto/caam/caamalg.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@
6060
#include <crypto/xts.h>
6161
#include <asm/unaligned.h>
6262
#include <linux/dma-mapping.h>
63+
#include <linux/device.h>
64+
#include <linux/err.h>
6365
#include <linux/kernel.h>
66+
#include <linux/slab.h>
67+
#include <linux/string.h>
6468

6569
/*
6670
* crypto alg
@@ -1000,6 +1004,13 @@ static void aead_crypt_done(struct device *jrdev, u32 *desc, u32 err,
10001004
crypto_finalize_aead_request(jrp->engine, req, ecode);
10011005
}
10021006

1007+
static inline u8 *skcipher_edesc_iv(struct skcipher_edesc *edesc)
1008+
{
1009+
1010+
return PTR_ALIGN((u8 *)edesc->sec4_sg + edesc->sec4_sg_bytes,
1011+
dma_get_cache_alignment());
1012+
}
1013+
10031014
static void skcipher_crypt_done(struct device *jrdev, u32 *desc, u32 err,
10041015
void *context)
10051016
{
@@ -1027,8 +1038,7 @@ static void skcipher_crypt_done(struct device *jrdev, u32 *desc, u32 err,
10271038
* This is used e.g. by the CTS mode.
10281039
*/
10291040
if (ivsize && !ecode) {
1030-
memcpy(req->iv, (u8 *)edesc->sec4_sg + edesc->sec4_sg_bytes,
1031-
ivsize);
1041+
memcpy(req->iv, skcipher_edesc_iv(edesc), ivsize);
10321042

10331043
print_hex_dump_debug("dstiv @" __stringify(__LINE__)": ",
10341044
DUMP_PREFIX_ADDRESS, 16, 4, req->iv,
@@ -1683,18 +1693,19 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
16831693
/*
16841694
* allocate space for base edesc and hw desc commands, link tables, IV
16851695
*/
1686-
aligned_size = ALIGN(ivsize, __alignof__(*edesc));
1687-
aligned_size += sizeof(*edesc) + desc_bytes + sec4_sg_bytes;
1696+
aligned_size = sizeof(*edesc) + desc_bytes + sec4_sg_bytes;
16881697
aligned_size = ALIGN(aligned_size, dma_get_cache_alignment());
1689-
iv = kzalloc(aligned_size, flags);
1690-
if (!iv) {
1698+
aligned_size += ~(ARCH_KMALLOC_MINALIGN - 1) &
1699+
(dma_get_cache_alignment() - 1);
1700+
aligned_size += ALIGN(ivsize, dma_get_cache_alignment());
1701+
edesc = kzalloc(aligned_size, flags);
1702+
if (!edesc) {
16911703
dev_err(jrdev, "could not allocate extended descriptor\n");
16921704
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
16931705
0, 0, 0);
16941706
return ERR_PTR(-ENOMEM);
16951707
}
16961708

1697-
edesc = (void *)(iv + ALIGN(ivsize, __alignof__(*edesc)));
16981709
edesc->src_nents = src_nents;
16991710
edesc->dst_nents = dst_nents;
17001711
edesc->mapped_src_nents = mapped_src_nents;
@@ -1706,6 +1717,7 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
17061717

17071718
/* Make sure IV is located in a DMAable area */
17081719
if (ivsize) {
1720+
iv = skcipher_edesc_iv(edesc);
17091721
memcpy(iv, req->iv, ivsize);
17101722

17111723
iv_dma = dma_map_single(jrdev, iv, ivsize, DMA_BIDIRECTIONAL);

drivers/crypto/caam/caamalg_qi.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
#include "caamalg_desc.h"
2121
#include <crypto/xts.h>
2222
#include <asm/unaligned.h>
23+
#include <linux/device.h>
24+
#include <linux/err.h>
2325
#include <linux/dma-mapping.h>
2426
#include <linux/kernel.h>
27+
#include <linux/string.h>
2528

2629
/*
2730
* crypto alg
@@ -1204,6 +1207,12 @@ static int ipsec_gcm_decrypt(struct aead_request *req)
12041207
false);
12051208
}
12061209

1210+
static inline u8 *skcipher_edesc_iv(struct skcipher_edesc *edesc)
1211+
{
1212+
return PTR_ALIGN((u8 *)&edesc->sgt[0] + edesc->qm_sg_bytes,
1213+
dma_get_cache_alignment());
1214+
}
1215+
12071216
static void skcipher_done(struct caam_drv_req *drv_req, u32 status)
12081217
{
12091218
struct skcipher_edesc *edesc;
@@ -1236,8 +1245,7 @@ static void skcipher_done(struct caam_drv_req *drv_req, u32 status)
12361245
* This is used e.g. by the CTS mode.
12371246
*/
12381247
if (!ecode)
1239-
memcpy(req->iv, (u8 *)&edesc->sgt[0] + edesc->qm_sg_bytes,
1240-
ivsize);
1248+
memcpy(req->iv, skcipher_edesc_iv(edesc), ivsize);
12411249

12421250
qi_cache_free(edesc);
12431251
skcipher_request_complete(req, ecode);
@@ -1259,6 +1267,7 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
12591267
int dst_sg_idx, qm_sg_ents, qm_sg_bytes;
12601268
struct qm_sg_entry *sg_table, *fd_sgt;
12611269
struct caam_drv_ctx *drv_ctx;
1270+
unsigned int len;
12621271

12631272
drv_ctx = get_drv_ctx(ctx, encrypt ? ENCRYPT : DECRYPT);
12641273
if (IS_ERR(drv_ctx))
@@ -1319,9 +1328,12 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
13191328
qm_sg_ents = 1 + pad_sg_nents(qm_sg_ents);
13201329

13211330
qm_sg_bytes = qm_sg_ents * sizeof(struct qm_sg_entry);
1322-
if (unlikely(ALIGN(ivsize, __alignof__(*edesc)) +
1323-
offsetof(struct skcipher_edesc, sgt) + qm_sg_bytes >
1324-
CAAM_QI_MEMCACHE_SIZE)) {
1331+
1332+
len = offsetof(struct skcipher_edesc, sgt) + qm_sg_bytes;
1333+
len = ALIGN(len, dma_get_cache_alignment());
1334+
len += ivsize;
1335+
1336+
if (unlikely(len > CAAM_QI_MEMCACHE_SIZE)) {
13251337
dev_err(qidev, "No space for %d S/G entries and/or %dB IV\n",
13261338
qm_sg_ents, ivsize);
13271339
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0,
@@ -1330,18 +1342,24 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
13301342
}
13311343

13321344
/* allocate space for base edesc, link tables and IV */
1333-
iv = qi_cache_alloc(flags);
1334-
if (unlikely(!iv)) {
1345+
edesc = qi_cache_alloc(flags);
1346+
if (unlikely(!edesc)) {
13351347
dev_err(qidev, "could not allocate extended descriptor\n");
13361348
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0,
13371349
0, DMA_NONE, 0, 0);
13381350
return ERR_PTR(-ENOMEM);
13391351
}
13401352

1341-
edesc = (void *)(iv + ALIGN(ivsize, __alignof__(*edesc)));
1353+
edesc->src_nents = src_nents;
1354+
edesc->dst_nents = dst_nents;
1355+
edesc->qm_sg_bytes = qm_sg_bytes;
1356+
edesc->drv_req.app_ctx = req;
1357+
edesc->drv_req.cbk = skcipher_done;
1358+
edesc->drv_req.drv_ctx = drv_ctx;
13421359

13431360
/* Make sure IV is located in a DMAable area */
13441361
sg_table = &edesc->sgt[0];
1362+
iv = skcipher_edesc_iv(edesc);
13451363
memcpy(iv, req->iv, ivsize);
13461364

13471365
iv_dma = dma_map_single(qidev, iv, ivsize, DMA_BIDIRECTIONAL);
@@ -1353,13 +1371,7 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
13531371
return ERR_PTR(-ENOMEM);
13541372
}
13551373

1356-
edesc->src_nents = src_nents;
1357-
edesc->dst_nents = dst_nents;
13581374
edesc->iv_dma = iv_dma;
1359-
edesc->qm_sg_bytes = qm_sg_bytes;
1360-
edesc->drv_req.app_ctx = req;
1361-
edesc->drv_req.cbk = skcipher_done;
1362-
edesc->drv_req.drv_ctx = drv_ctx;
13631375

13641376
dma_to_qm_sg_one(sg_table, iv_dma, ivsize, 0);
13651377
sg_to_qm_sg(req->src, req->cryptlen, sg_table + 1, 0);

drivers/crypto/caam/qi.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
*/
99

1010
#include <linux/cpumask.h>
11+
#include <linux/device.h>
12+
#include <linux/dma-mapping.h>
13+
#include <linux/kernel.h>
1114
#include <linux/kthread.h>
15+
#include <linux/netdevice.h>
16+
#include <linux/slab.h>
17+
#include <linux/string.h>
1218
#include <soc/fsl/qman.h>
1319

1420
#include "debugfs.h"
@@ -755,8 +761,8 @@ int caam_qi_init(struct platform_device *caam_pdev)
755761
napi_enable(irqtask);
756762
}
757763

758-
qi_cache = kmem_cache_create("caamqicache", CAAM_QI_MEMCACHE_SIZE, 0,
759-
0, NULL);
764+
qi_cache = kmem_cache_create("caamqicache", CAAM_QI_MEMCACHE_SIZE,
765+
dma_get_cache_alignment(), 0, NULL);
760766
if (!qi_cache) {
761767
dev_err(qidev, "Can't allocate CAAM cache\n");
762768
free_rsp_fqs();

0 commit comments

Comments
 (0)