]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/zcrypt: Fix memory leak with CCA cards used as accelerator
authorHarald Freudenberger <freude@linux.ibm.com>
Thu, 19 Mar 2026 08:06:52 +0000 (09:06 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 24 Mar 2026 19:57:31 +0000 (20:57 +0100)
Tests showed that there is a memory leak if CCA cards are used as
accelerator for clear key RSA requests (ME and CRT). With the last
rework for the memory allocation the AP messages are allocated by
ap_init_apmsg() but for some reason on two places (ME and CRT) the
older allocation was still in place. So the first allocation simple
was never freed.

Fixes: 57db62a130ce ("s390/ap/zcrypt: Rework AP message buffer allocation")
Reported-by: Yi Zhang <yi.zhang@redhat.com>
Closes: https://lore.kernel.org/linux-s390/CAHj4cs9H67Uz0iVaRQv447p7JFPRPy3TKAT4=Y6_e=wSHCZM5w@mail.gmail.com/
Reported-by: Nadja Hariz <Nadia.Hariz@ibm.com>
Cc: stable@vger.kernel.org
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
drivers/s390/crypto/zcrypt_msgtype6.c

index a0dcab5dc4f2f7a1409eaa80b522563aac10b9db..23a32221e41a77586f638c773afebbd839c840eb 100644 (file)
@@ -953,6 +953,10 @@ static atomic_t zcrypt_step = ATOMIC_INIT(0);
 /*
  * The request distributor calls this function if it picked the CEXxC
  * device to handle a modexpo request.
+ * This function assumes that ap_msg has been initialized with
+ * ap_init_apmsg() and thus a valid buffer with the size of
+ * ap_msg->bufsize is available within ap_msg. Also the caller has
+ * to make sure ap_release_apmsg() is always called even on failure.
  * @zq: pointer to zcrypt_queue structure that identifies the
  *     CEXxC device to the request distributor
  * @mex: pointer to the modexpo request buffer
@@ -964,21 +968,17 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_queue *zq,
        struct ap_response_type *resp_type = &ap_msg->response;
        int rc;
 
-       ap_msg->msg = (void *)get_zeroed_page(GFP_KERNEL);
-       if (!ap_msg->msg)
-               return -ENOMEM;
-       ap_msg->bufsize = PAGE_SIZE;
        ap_msg->receive = zcrypt_msgtype6_receive;
        ap_msg->psmid = (((unsigned long)current->pid) << 32) +
                atomic_inc_return(&zcrypt_step);
        rc = icamex_msg_to_type6mex_msgx(zq, ap_msg, mex);
        if (rc)
-               goto out_free;
+               goto out;
        resp_type->type = CEXXC_RESPONSE_TYPE_ICA;
        init_completion(&resp_type->work);
        rc = ap_queue_message(zq->queue, ap_msg);
        if (rc)
-               goto out_free;
+               goto out;
        rc = wait_for_completion_interruptible(&resp_type->work);
        if (rc == 0) {
                rc = ap_msg->rc;
@@ -991,15 +991,17 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_queue *zq,
                ap_cancel_message(zq->queue, ap_msg);
        }
 
-out_free:
-       free_page((unsigned long)ap_msg->msg);
-       ap_msg->msg = NULL;
+out:
        return rc;
 }
 
 /*
  * The request distributor calls this function if it picked the CEXxC
  * device to handle a modexpo_crt request.
+ * This function assumes that ap_msg has been initialized with
+ * ap_init_apmsg() and thus a valid buffer with the size of
+ * ap_msg->bufsize is available within ap_msg. Also the caller has
+ * to make sure ap_release_apmsg() is always called even on failure.
  * @zq: pointer to zcrypt_queue structure that identifies the
  *     CEXxC device to the request distributor
  * @crt: pointer to the modexpoc_crt request buffer
@@ -1011,21 +1013,17 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
        struct ap_response_type *resp_type = &ap_msg->response;
        int rc;
 
-       ap_msg->msg = (void *)get_zeroed_page(GFP_KERNEL);
-       if (!ap_msg->msg)
-               return -ENOMEM;
-       ap_msg->bufsize = PAGE_SIZE;
        ap_msg->receive = zcrypt_msgtype6_receive;
        ap_msg->psmid = (((unsigned long)current->pid) << 32) +
                atomic_inc_return(&zcrypt_step);
        rc = icacrt_msg_to_type6crt_msgx(zq, ap_msg, crt);
        if (rc)
-               goto out_free;
+               goto out;
        resp_type->type = CEXXC_RESPONSE_TYPE_ICA;
        init_completion(&resp_type->work);
        rc = ap_queue_message(zq->queue, ap_msg);
        if (rc)
-               goto out_free;
+               goto out;
        rc = wait_for_completion_interruptible(&resp_type->work);
        if (rc == 0) {
                rc = ap_msg->rc;
@@ -1038,9 +1036,7 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
                ap_cancel_message(zq->queue, ap_msg);
        }
 
-out_free:
-       free_page((unsigned long)ap_msg->msg);
-       ap_msg->msg = NULL;
+out:
        return rc;
 }