diff options
author | Yunfeng Ye <yeyunfeng@huawei.com> | 2019-09-15 17:26:56 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-10-07 18:57:16 +0200 |
commit | d983182d40022445076d531f8d69113d6699a88b (patch) | |
tree | c5d534456c220f2d4bbcb7467189fb1b0b977123 /drivers/crypto | |
parent | 22c788ba7a52881f2458b5571c2e36fb3a3f74f3 (diff) | |
download | linux-stable-d983182d40022445076d531f8d69113d6699a88b.tar.gz linux-stable-d983182d40022445076d531f8d69113d6699a88b.tar.bz2 linux-stable-d983182d40022445076d531f8d69113d6699a88b.zip |
crypto: hisilicon - Fix double free in sec_free_hw_sgl()
[ Upstream commit 24fbf7bad888767bed952f540ac963bc57e47e15 ]
There are two problems in sec_free_hw_sgl():
First, when sgl_current->next is valid, @hw_sgl will be freed in the
first loop, but it free again after the loop.
Second, sgl_current and sgl_current->next_sgl is not match when
dma_pool_free() is invoked, the third parameter should be the dma
address of sgl_current, but sgl_current->next_sgl is the dma address
of next chain, so use sgl_current->next_sgl is wrong.
Fix this by deleting the last dma_pool_free() in sec_free_hw_sgl(),
modifying the condition for while loop, and matching the address for
dma_pool_free().
Fixes: 915e4e8413da ("crypto: hisilicon - SEC security accelerator driver")
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/hisilicon/sec/sec_algs.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/crypto/hisilicon/sec/sec_algs.c b/drivers/crypto/hisilicon/sec/sec_algs.c index cdc4f9a171d9..db2983c51f1e 100644 --- a/drivers/crypto/hisilicon/sec/sec_algs.c +++ b/drivers/crypto/hisilicon/sec/sec_algs.c @@ -215,17 +215,18 @@ static void sec_free_hw_sgl(struct sec_hw_sgl *hw_sgl, dma_addr_t psec_sgl, struct sec_dev_info *info) { struct sec_hw_sgl *sgl_current, *sgl_next; + dma_addr_t sgl_next_dma; - if (!hw_sgl) - return; sgl_current = hw_sgl; - while (sgl_current->next) { + while (sgl_current) { sgl_next = sgl_current->next; - dma_pool_free(info->hw_sgl_pool, sgl_current, - sgl_current->next_sgl); + sgl_next_dma = sgl_current->next_sgl; + + dma_pool_free(info->hw_sgl_pool, sgl_current, psec_sgl); + sgl_current = sgl_next; + psec_sgl = sgl_next_dma; } - dma_pool_free(info->hw_sgl_pool, hw_sgl, psec_sgl); } static int sec_alg_skcipher_setkey(struct crypto_skcipher *tfm, |