]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
crypto: hisilicon/debugfs - Fix debugfs uninit process issue
authorChenghai Huang <huangchenghai2@huawei.com>
Sun, 7 Apr 2024 07:59:53 +0000 (15:59 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 Jul 2024 10:49:02 +0000 (12:49 +0200)
[ Upstream commit 8be0913389718e8d27c4f1d4537b5e1b99ed7739 ]

During the zip probe process, the debugfs failure does not stop
the probe. When debugfs initialization fails, jumping to the
error branch will also release regs, in addition to its own
rollback operation.

As a result, it may be released repeatedly during the regs
uninit process. Therefore, the null check needs to be added to
the regs uninit process.

Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/crypto/hisilicon/debugfs.c

index 2cc1591949db7e078846115e5bd646e6afe2e37f..bd205f1f2279e485b01164579616236d1830b55f 100644 (file)
@@ -794,8 +794,14 @@ static void dfx_regs_uninit(struct hisi_qm *qm,
 {
        int i;
 
+       if (!dregs)
+               return;
+
        /* Setting the pointer is NULL to prevent double free */
        for (i = 0; i < reg_len; i++) {
+               if (!dregs[i].regs)
+                       continue;
+
                kfree(dregs[i].regs);
                dregs[i].regs = NULL;
        }
@@ -845,14 +851,21 @@ alloc_error:
 static int qm_diff_regs_init(struct hisi_qm *qm,
                struct dfx_diff_registers *dregs, u32 reg_len)
 {
+       int ret;
+
        qm->debug.qm_diff_regs = dfx_regs_init(qm, qm_diff_regs, ARRAY_SIZE(qm_diff_regs));
-       if (IS_ERR(qm->debug.qm_diff_regs))
-               return PTR_ERR(qm->debug.qm_diff_regs);
+       if (IS_ERR(qm->debug.qm_diff_regs)) {
+               ret = PTR_ERR(qm->debug.qm_diff_regs);
+               qm->debug.qm_diff_regs = NULL;
+               return ret;
+       }
 
        qm->debug.acc_diff_regs = dfx_regs_init(qm, dregs, reg_len);
        if (IS_ERR(qm->debug.acc_diff_regs)) {
                dfx_regs_uninit(qm, qm->debug.qm_diff_regs, ARRAY_SIZE(qm_diff_regs));
-               return PTR_ERR(qm->debug.acc_diff_regs);
+               ret = PTR_ERR(qm->debug.acc_diff_regs);
+               qm->debug.acc_diff_regs = NULL;
+               return ret;
        }
 
        return 0;
@@ -893,7 +906,9 @@ static int qm_last_regs_init(struct hisi_qm *qm)
 static void qm_diff_regs_uninit(struct hisi_qm *qm, u32 reg_len)
 {
        dfx_regs_uninit(qm, qm->debug.acc_diff_regs, reg_len);
+       qm->debug.acc_diff_regs = NULL;
        dfx_regs_uninit(qm, qm->debug.qm_diff_regs, ARRAY_SIZE(qm_diff_regs));
+       qm->debug.qm_diff_regs = NULL;
 }
 
 /**