s390/ap/zcrypt: Rework AP message buffer allocation
authorHarald Freudenberger <freude@linux.ibm.com>
Thu, 24 Apr 2025 13:35:56 +0000 (15:35 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Wed, 30 Apr 2025 09:34:00 +0000 (11:34 +0200)
Slight rework on the way how AP message buffers are allocated.
Instead of having multiple places with kmalloc() calls all
the AP message buffers are now allocated and freed on exactly
one place: ap_init_apmsg() allocates the current AP bus max
limit of ap_max_msg_size (defaults to 12KB). The AP message
buffer is then freed in ap_release_apmsg().

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Link: https://lore.kernel.org/r/20250424133619.16495-3-freude@linux.ibm.com
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_msgtype50.c
drivers/s390/crypto/zcrypt_msgtype6.c

index 1564cd7e3f598ac31a66e0402db1f8b53197629e..8935b3ee3a331723e447b152394700568bfa8ce1 100644 (file)
@@ -547,6 +547,32 @@ static void ap_poll_thread_stop(void)
 #define is_card_dev(x) ((x)->parent == ap_root_device)
 #define is_queue_dev(x) ((x)->parent != ap_root_device)
 
+/*
+ * ap_init_apmsg() - Initialize ap_message.
+ */
+int ap_init_apmsg(struct ap_message *ap_msg)
+{
+       unsigned int maxmsgsize = atomic_read(&ap_max_msg_size);
+
+       memset(ap_msg, 0, sizeof(*ap_msg));
+       ap_msg->msg = kmalloc(maxmsgsize, GFP_KERNEL);
+       if (!ap_msg->msg)
+               return -ENOMEM;
+       ap_msg->bufsize = maxmsgsize;
+
+       return 0;
+}
+EXPORT_SYMBOL(ap_init_apmsg);
+
+/*
+ * ap_release_apmsg() - Release ap_message.
+ */
+void ap_release_apmsg(struct ap_message *ap_msg)
+{
+       kfree_sensitive(ap_msg->msg);
+}
+EXPORT_SYMBOL(ap_release_apmsg);
+
 /**
  * ap_bus_match()
  * @dev: Pointer to device
index 7fd24c207bdf5ca3d2f2053d467608117a8f0111..483231bcdea6f617b1bfbed7d2a365cb46365cc1 100644 (file)
@@ -237,25 +237,8 @@ struct ap_message {
 #define AP_MSG_FLAG_USAGE    0x0002    /* CCA, EP11: usage (no admin) msg */
 #define AP_MSG_FLAG_ADMIN    0x0004    /* CCA, EP11: admin (=control) msg */
 
-/**
- * ap_init_message() - Initialize ap_message.
- * Initialize a message before using. Otherwise this might result in
- * unexpected behaviour.
- */
-static inline void ap_init_message(struct ap_message *ap_msg)
-{
-       memset(ap_msg, 0, sizeof(*ap_msg));
-}
-
-/**
- * ap_release_message() - Release ap_message.
- * Releases all memory used internal within the ap_message struct
- * Currently this is the message and private field.
- */
-static inline void ap_release_message(struct ap_message *ap_msg)
-{
-       kfree_sensitive(ap_msg->msg);
-}
+int ap_init_apmsg(struct ap_message *ap_msg);
+void ap_release_apmsg(struct ap_message *ap_msg);
 
 enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event);
 enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event);
index 5020696f13797de76c8d5877bacef77d9e102d2c..8c263a9b643db2944bb7f6e9a3e4d285fa2575e3 100644 (file)
@@ -642,16 +642,17 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
        struct zcrypt_queue *zq, *pref_zq;
        struct ap_message ap_msg;
        unsigned int wgt = 0, pref_wgt = 0;
-       unsigned int func_code;
-       int cpen, qpen, qid = 0, rc = -ENODEV;
+       unsigned int func_code = 0;
+       int cpen, qpen, qid = 0, rc;
        struct module *mod;
 
        trace_s390_zcrypt_req(mex, TP_ICARSAMODEXPO);
 
-       ap_init_message(&ap_msg);
+       rc = ap_init_apmsg(&ap_msg);
+       if (rc)
+               goto out;
 
        if (mex->outputdatalength < mex->inputdatalength) {
-               func_code = 0;
                rc = -EINVAL;
                goto out;
        }
@@ -728,7 +729,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
        spin_unlock(&zcrypt_list_lock);
 
 out:
-       ap_release_message(&ap_msg);
+       ap_release_apmsg(&ap_msg);
        if (tr) {
                tr->last_rc = rc;
                tr->last_qid = qid;
@@ -746,16 +747,17 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
        struct zcrypt_queue *zq, *pref_zq;
        struct ap_message ap_msg;
        unsigned int wgt = 0, pref_wgt = 0;
-       unsigned int func_code;
-       int cpen, qpen, qid = 0, rc = -ENODEV;
+       unsigned int func_code = 0;
+       int cpen, qpen, qid = 0, rc;
        struct module *mod;
 
        trace_s390_zcrypt_req(crt, TP_ICARSACRT);
 
-       ap_init_message(&ap_msg);
+       rc = ap_init_apmsg(&ap_msg);
+       if (rc)
+               goto out;
 
        if (crt->outputdatalength < crt->inputdatalength) {
-               func_code = 0;
                rc = -EINVAL;
                goto out;
        }
@@ -832,7 +834,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
        spin_unlock(&zcrypt_list_lock);
 
 out:
-       ap_release_message(&ap_msg);
+       ap_release_apmsg(&ap_msg);
        if (tr) {
                tr->last_rc = rc;
                tr->last_qid = qid;
@@ -850,15 +852,18 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
        struct zcrypt_queue *zq, *pref_zq;
        struct ap_message ap_msg;
        unsigned int wgt = 0, pref_wgt = 0;
-       unsigned int func_code;
+       unsigned int func_code = 0;
        unsigned short *domain, tdom;
-       int cpen, qpen, qid = 0, rc = -ENODEV;
+       int cpen, qpen, qid = 0, rc;
        struct module *mod;
 
        trace_s390_zcrypt_req(xcrb, TB_ZSECSENDCPRB);
 
        xcrb->status = 0;
-       ap_init_message(&ap_msg);
+
+       rc = ap_init_apmsg(&ap_msg);
+       if (rc)
+               goto out;
 
        rc = prep_cca_ap_msg(userspace, xcrb, &ap_msg, &func_code, &domain);
        if (rc)
@@ -962,7 +967,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
        spin_unlock(&zcrypt_list_lock);
 
 out:
-       ap_release_message(&ap_msg);
+       ap_release_apmsg(&ap_msg);
        if (tr) {
                tr->last_rc = rc;
                tr->last_qid = qid;
@@ -1033,14 +1038,16 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
        struct ep11_target_dev *targets;
        unsigned short target_num;
        unsigned int wgt = 0, pref_wgt = 0;
-       unsigned int func_code, domain;
+       unsigned int func_code = 0, domain;
        struct ap_message ap_msg;
-       int cpen, qpen, qid = 0, rc = -ENODEV;
+       int cpen, qpen, qid = 0, rc;
        struct module *mod;
 
        trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB);
 
-       ap_init_message(&ap_msg);
+       rc = ap_init_apmsg(&ap_msg);
+       if (rc)
+               goto out;
 
        target_num = (unsigned short)xcrb->targets_num;
 
@@ -1164,7 +1171,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
 out_free:
        kfree(targets);
 out:
-       ap_release_message(&ap_msg);
+       ap_release_apmsg(&ap_msg);
        if (tr) {
                tr->last_rc = rc;
                tr->last_qid = qid;
@@ -1204,7 +1211,7 @@ static long zcrypt_rng(char *buffer)
        struct zcrypt_card *zc, *pref_zc;
        struct zcrypt_queue *zq, *pref_zq;
        unsigned int wgt = 0, pref_wgt = 0;
-       unsigned int func_code;
+       unsigned int func_code = 0;
        struct ap_message ap_msg;
        unsigned int domain;
        int qid = 0, rc = -ENODEV;
@@ -1212,7 +1219,9 @@ static long zcrypt_rng(char *buffer)
 
        trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB);
 
-       ap_init_message(&ap_msg);
+       rc = ap_init_apmsg(&ap_msg);
+       if (rc)
+               goto out;
        rc = prep_rng_ap_msg(&ap_msg, &func_code, &domain);
        if (rc)
                goto out;
@@ -1258,7 +1267,7 @@ static long zcrypt_rng(char *buffer)
        spin_unlock(&zcrypt_list_lock);
 
 out:
-       ap_release_message(&ap_msg);
+       ap_release_apmsg(&ap_msg);
        trace_s390_zcrypt_rep(buffer, func_code, rc,
                              AP_QID_CARD(qid), AP_QID_QUEUE(qid));
        return rc;
index 47c401f5409b3a5dd43baa8dd2b517958b4747fa..fc0a2a053dc22cc488b85f0fd9e7b30a08f9f3f5 100644 (file)
@@ -449,6 +449,10 @@ static atomic_t zcrypt_step = ATOMIC_INIT(0);
  * @zq: pointer to zcrypt_queue structure that identifies the
  *     CEXxA device to the request distributor
  * @mex: pointer to the modexpo request buffer
+ * 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.
  */
 static long zcrypt_msgtype50_modexpo(struct zcrypt_queue *zq,
                                     struct ica_rsa_modexpo *mex,
@@ -456,10 +460,8 @@ static long zcrypt_msgtype50_modexpo(struct zcrypt_queue *zq,
 {
        int rc;
 
-       ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
-       ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
-       if (!ap_msg->msg)
-               return -ENOMEM;
+       if (ap_msg->bufsize < MSGTYPE50_CRB3_MAX_MSG_SIZE)
+               return -EMSGSIZE;
        ap_msg->receive = zcrypt_msgtype50_receive;
        ap_msg->psmid = (((unsigned long)current->pid) << 32) +
                atomic_inc_return(&zcrypt_step);
@@ -496,6 +498,10 @@ out:
  * @zq: pointer to zcrypt_queue structure that identifies the
  *     CEXxA device to the request distributor
  * @crt: pointer to the modexpoc_crt request buffer
+ * 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.
  */
 static long zcrypt_msgtype50_modexpo_crt(struct zcrypt_queue *zq,
                                         struct ica_rsa_modexpo_crt *crt,
@@ -503,10 +509,8 @@ static long zcrypt_msgtype50_modexpo_crt(struct zcrypt_queue *zq,
 {
        int rc;
 
-       ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
-       ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
-       if (!ap_msg->msg)
-               return -ENOMEM;
+       if (ap_msg->bufsize < MSGTYPE50_CRB3_MAX_MSG_SIZE)
+               return -EMSGSIZE;
        ap_msg->receive = zcrypt_msgtype50_receive;
        ap_msg->psmid = (((unsigned long)current->pid) << 32) +
                atomic_inc_return(&zcrypt_step);
index 09ef91af1e2af22314a949fa3678a1783c698973..9cefbb30960fdd70fcb016e89ebe1aefd4049c02 100644 (file)
@@ -1050,9 +1050,10 @@ out_free:
  * Prepare a CCA AP msg: fetch the required data from userspace,
  * prepare the AP msg, fill some info into the ap_message struct,
  * extract some data from the CPRB and give back to the caller.
- * This function allocates memory and needs an ap_msg prepared
- * by the caller with ap_init_message(). Also the caller has to
- * make sure ap_release_message() is always called even on failure.
+ * 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.
  */
 int prep_cca_ap_msg(bool userspace, struct ica_xcRB *xcrb,
                    struct ap_message *ap_msg,
@@ -1060,10 +1061,6 @@ int prep_cca_ap_msg(bool userspace, struct ica_xcRB *xcrb,
 {
        struct ap_response_type *resp_type = &ap_msg->response;
 
-       ap_msg->bufsize = atomic_read(&ap_max_msg_size);
-       ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
-       if (!ap_msg->msg)
-               return -ENOMEM;
        ap_msg->receive = zcrypt_msgtype6_receive;
        ap_msg->psmid = (((unsigned long)current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
@@ -1143,9 +1140,10 @@ out:
  * Prepare an EP11 AP msg: fetch the required data from userspace,
  * prepare the AP msg, fill some info into the ap_message struct,
  * extract some data from the CPRB and give back to the caller.
- * This function allocates memory and needs an ap_msg prepared
- * by the caller with ap_init_message(). Also the caller has to
- * make sure ap_release_message() is always called even on failure.
+ * 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.
  */
 int prep_ep11_ap_msg(bool userspace, struct ep11_urb *xcrb,
                     struct ap_message *ap_msg,
@@ -1153,10 +1151,6 @@ int prep_ep11_ap_msg(bool userspace, struct ep11_urb *xcrb,
 {
        struct ap_response_type *resp_type = &ap_msg->response;
 
-       ap_msg->bufsize = atomic_read(&ap_max_msg_size);
-       ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
-       if (!ap_msg->msg)
-               return -ENOMEM;
        ap_msg->receive = zcrypt_msgtype6_receive_ep11;
        ap_msg->psmid = (((unsigned long)current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
@@ -1257,15 +1251,20 @@ out:
        return rc;
 }
 
+/*
+ * Prepare a CEXXC get random request ap message.
+ * This function assumes that ap_msg has been initialized with
+ * ap_init_apmsg() and thus a valid buffer with the size of
+ * ap_max_msg_size is available within ap_msg. Also the caller has
+ * to make sure ap_release_apmsg() is always called even on failure.
+ */
 int prep_rng_ap_msg(struct ap_message *ap_msg, int *func_code,
                    unsigned int *domain)
 {
        struct ap_response_type *resp_type = &ap_msg->response;
 
-       ap_msg->bufsize = AP_DEFAULT_MAX_MSG_SIZE;
-       ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
-       if (!ap_msg->msg)
-               return -ENOMEM;
+       if (ap_msg->bufsize < AP_DEFAULT_MAX_MSG_SIZE)
+               return -EMSGSIZE;
        ap_msg->receive = zcrypt_msgtype6_receive;
        ap_msg->psmid = (((unsigned long)current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);