Skip to content

Commit 7850c91

Browse files
Boris BREZILLONherbertx
authored andcommitted
crypto: marvell/cesa - fix memory leak
Crypto requests are not guaranteed to be finalized (->final() call), and can be freed at any moment, without getting any notification from the core. This can lead to memory leaks of the ->cache buffer. Make this buffer part of the request object, and allocate an extra buffer from the DMA cache pool when doing DMA operations. As a side effect, this patch also fixes another bug related to cache allocation and DMA operations. When the core allocates a new request and import an existing state, a cache buffer can be allocated (depending on the state). The problem is, at that very moment, we don't know yet whether the request will use DMA or not, and since everything is likely to be initialized to zero, mv_cesa_ahash_alloc_cache() thinks it should allocate a buffer for standard operation. But when mv_cesa_ahash_free_cache() is called, req->type has been set to CESA_DMA_REQ in the meantime, thus leading to an invalind dma_pool_free() call (the buffer passed in argument has not been allocated from the pool). Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Reported-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 03a6f29 commit 7850c91

File tree

2 files changed

+20
-69
lines changed

2 files changed

+20
-69
lines changed

drivers/crypto/marvell/cesa.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ struct mv_cesa_ahash_dma_req {
588588
struct mv_cesa_tdma_req base;
589589
u8 *padding;
590590
dma_addr_t padding_dma;
591+
u8 *cache;
591592
dma_addr_t cache_dma;
592593
};
593594

@@ -609,7 +610,7 @@ struct mv_cesa_ahash_req {
609610
struct mv_cesa_ahash_std_req std;
610611
} req;
611612
struct mv_cesa_op_ctx op_tmpl;
612-
u8 *cache;
613+
u8 cache[CESA_MAX_HASH_BLOCK_SIZE];
613614
unsigned int cache_ptr;
614615
u64 len;
615616
int src_nents;

drivers/crypto/marvell/hash.c

Lines changed: 18 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -45,69 +45,25 @@ mv_cesa_ahash_req_iter_next_op(struct mv_cesa_ahash_dma_iter *iter)
4545
return mv_cesa_req_dma_iter_next_op(&iter->base);
4646
}
4747

48-
static inline int mv_cesa_ahash_dma_alloc_cache(struct mv_cesa_ahash_req *creq,
49-
gfp_t flags)
48+
static inline int
49+
mv_cesa_ahash_dma_alloc_cache(struct mv_cesa_ahash_dma_req *req, gfp_t flags)
5050
{
51-
struct mv_cesa_ahash_dma_req *dreq = &creq->req.dma;
52-
53-
creq->cache = dma_pool_alloc(cesa_dev->dma->cache_pool, flags,
54-
&dreq->cache_dma);
55-
if (!creq->cache)
56-
return -ENOMEM;
57-
58-
return 0;
59-
}
60-
61-
static inline int mv_cesa_ahash_std_alloc_cache(struct mv_cesa_ahash_req *creq,
62-
gfp_t flags)
63-
{
64-
creq->cache = kzalloc(CESA_MAX_HASH_BLOCK_SIZE, flags);
65-
if (!creq->cache)
51+
req->cache = dma_pool_alloc(cesa_dev->dma->cache_pool, flags,
52+
&req->cache_dma);
53+
if (!req->cache)
6654
return -ENOMEM;
6755

6856
return 0;
6957
}
7058

71-
static int mv_cesa_ahash_alloc_cache(struct ahash_request *req)
72-
{
73-
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
74-
gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
75-
GFP_KERNEL : GFP_ATOMIC;
76-
int ret;
77-
78-
if (creq->cache)
79-
return 0;
80-
81-
if (creq->req.base.type == CESA_DMA_REQ)
82-
ret = mv_cesa_ahash_dma_alloc_cache(creq, flags);
83-
else
84-
ret = mv_cesa_ahash_std_alloc_cache(creq, flags);
85-
86-
return ret;
87-
}
88-
89-
static inline void mv_cesa_ahash_dma_free_cache(struct mv_cesa_ahash_req *creq)
90-
{
91-
dma_pool_free(cesa_dev->dma->cache_pool, creq->cache,
92-
creq->req.dma.cache_dma);
93-
}
94-
95-
static inline void mv_cesa_ahash_std_free_cache(struct mv_cesa_ahash_req *creq)
96-
{
97-
kfree(creq->cache);
98-
}
99-
100-
static void mv_cesa_ahash_free_cache(struct mv_cesa_ahash_req *creq)
59+
static inline void
60+
mv_cesa_ahash_dma_free_cache(struct mv_cesa_ahash_dma_req *req)
10161
{
102-
if (!creq->cache)
62+
if (!req->cache)
10363
return;
10464

105-
if (creq->req.base.type == CESA_DMA_REQ)
106-
mv_cesa_ahash_dma_free_cache(creq);
107-
else
108-
mv_cesa_ahash_std_free_cache(creq);
109-
110-
creq->cache = NULL;
65+
dma_pool_free(cesa_dev->dma->cache_pool, req->cache,
66+
req->cache_dma);
11167
}
11268

11369
static int mv_cesa_ahash_dma_alloc_padding(struct mv_cesa_ahash_dma_req *req,
@@ -146,6 +102,7 @@ static inline void mv_cesa_ahash_dma_cleanup(struct ahash_request *req)
146102
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
147103

148104
dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, DMA_TO_DEVICE);
105+
mv_cesa_ahash_dma_free_cache(&creq->req.dma);
149106
mv_cesa_dma_cleanup(&creq->req.dma.base);
150107
}
151108

@@ -161,8 +118,6 @@ static void mv_cesa_ahash_last_cleanup(struct ahash_request *req)
161118
{
162119
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
163120

164-
mv_cesa_ahash_free_cache(creq);
165-
166121
if (creq->req.base.type == CESA_DMA_REQ)
167122
mv_cesa_ahash_dma_last_cleanup(req);
168123
}
@@ -445,14 +400,6 @@ static inline int mv_cesa_ahash_cra_init(struct crypto_tfm *tfm)
445400
static int mv_cesa_ahash_cache_req(struct ahash_request *req, bool *cached)
446401
{
447402
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
448-
int ret;
449-
450-
if (((creq->cache_ptr + req->nbytes) & CESA_HASH_BLOCK_SIZE_MSK) &&
451-
!creq->last_req) {
452-
ret = mv_cesa_ahash_alloc_cache(req);
453-
if (ret)
454-
return ret;
455-
}
456403

457404
if (creq->cache_ptr + req->nbytes < 64 && !creq->last_req) {
458405
*cached = true;
@@ -505,10 +452,17 @@ mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain,
505452
gfp_t flags)
506453
{
507454
struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
455+
int ret;
508456

509457
if (!creq->cache_ptr)
510458
return 0;
511459

460+
ret = mv_cesa_ahash_dma_alloc_cache(ahashdreq, flags);
461+
if (ret)
462+
return ret;
463+
464+
memcpy(ahashdreq->cache, creq->cache, creq->cache_ptr);
465+
512466
return mv_cesa_dma_add_data_transfer(chain,
513467
CESA_SA_DATA_SRAM_OFFSET,
514468
ahashdreq->cache_dma,
@@ -848,10 +802,6 @@ static int mv_cesa_ahash_import(struct ahash_request *req, const void *hash,
848802
if (!cache_ptr)
849803
return 0;
850804

851-
ret = mv_cesa_ahash_alloc_cache(req);
852-
if (ret)
853-
return ret;
854-
855805
memcpy(creq->cache, cache, cache_ptr);
856806
creq->cache_ptr = cache_ptr;
857807

0 commit comments

Comments
 (0)