s390/zcrypt: Rework cca findcard() implementation and callers
authorHarald Freudenberger <freude@linux.ibm.com>
Thu, 24 Apr 2025 13:36:07 +0000 (15:36 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Wed, 30 Apr 2025 09:34:01 +0000 (11:34 +0200)
Rework the memory usage of the cca findcard() implementation:
- findcard does not allocate memory for the list of apqns
  any more.
- the callers are now responsible to provide an array of
  apqns to store the matching apqns into.

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-14-freude@linux.ibm.com
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
drivers/s390/crypto/pkey_cca.c
drivers/s390/crypto/zcrypt_ccamisc.c
drivers/s390/crypto/zcrypt_ccamisc.h

index 83b02a466346711ecc74fb18630652d658703c0a..50cbcb91565f54e5bbc0119720c8d9ef588ec0fc 100644 (file)
@@ -73,7 +73,7 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
                         struct pkey_apqn *apqns, size_t *nr_apqns)
 {
        struct keytoken_header *hdr = (struct keytoken_header *)key;
-       u32 _nr_apqns, *_apqns = NULL;
+       u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
        int rc;
 
        if (!flags)
@@ -107,7 +107,7 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
                        /* unknown CCA internal token type */
                        return -EINVAL;
                }
-               rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+               rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
                                   minhwtype, AES_MK_SET,
                                   cur_mkvp, old_mkvp);
                if (rc)
@@ -126,7 +126,7 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
                        /* unknown CCA internal 2 token type */
                        return -EINVAL;
                }
-               rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+               rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
                                   ZCRYPT_CEX7, APKA_MK_SET,
                                   cur_mkvp, old_mkvp);
                if (rc)
@@ -147,7 +147,6 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
        *nr_apqns = _nr_apqns;
 
 out:
-       kfree(_apqns);
        pr_debug("rc=%d\n", rc);
        return rc;
 }
@@ -156,7 +155,7 @@ static int cca_apqns4type(enum pkey_key_type ktype,
                          u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
                          struct pkey_apqn *apqns, size_t *nr_apqns)
 {
-       u32 _nr_apqns, *_apqns = NULL;
+       u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
        int rc;
 
        zcrypt_wait_api_operational();
@@ -171,7 +170,7 @@ static int cca_apqns4type(enum pkey_key_type ktype,
                        old_mkvp = *((u64 *)alt_mkvp);
                if (ktype == PKEY_TYPE_CCA_CIPHER)
                        minhwtype = ZCRYPT_CEX6;
-               rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+               rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
                                   minhwtype, AES_MK_SET,
                                   cur_mkvp, old_mkvp);
                if (rc)
@@ -184,7 +183,7 @@ static int cca_apqns4type(enum pkey_key_type ktype,
                        cur_mkvp = *((u64 *)cur_mkvp);
                if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
                        old_mkvp = *((u64 *)alt_mkvp);
-               rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+               rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
                                   ZCRYPT_CEX7, APKA_MK_SET,
                                   cur_mkvp, old_mkvp);
                if (rc)
@@ -205,7 +204,6 @@ static int cca_apqns4type(enum pkey_key_type ktype,
        *nr_apqns = _nr_apqns;
 
 out:
-       kfree(_apqns);
        pr_debug("rc=%d\n", rc);
        return rc;
 }
@@ -461,7 +459,7 @@ static int cca_verifykey(const u8 *key, u32 keylen,
                         u32 *keytype, u32 *keybitsize, u32 *flags)
 {
        struct keytoken_header *hdr = (struct keytoken_header *)key;
-       u32 nr_apqns, *apqns = NULL;
+       u32 apqns[MAXAPQNSINLIST], nr_apqns = ARRAY_SIZE(apqns);
        int rc;
 
        if (keylen < sizeof(*hdr))
@@ -478,13 +476,14 @@ static int cca_verifykey(const u8 *key, u32 keylen,
                        goto out;
                *keytype = PKEY_TYPE_CCA_DATA;
                *keybitsize = t->bitsize;
-               rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
+               rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
                                   ZCRYPT_CEX3C, AES_MK_SET,
                                   t->mkvp, 0);
                if (!rc)
                        *flags = PKEY_FLAGS_MATCH_CUR_MKVP;
                if (rc == -ENODEV) {
-                       rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
+                       nr_apqns = ARRAY_SIZE(apqns);
+                       rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
                                           ZCRYPT_CEX3C, AES_MK_SET,
                                           0, t->mkvp);
                        if (!rc)
@@ -511,13 +510,14 @@ static int cca_verifykey(const u8 *key, u32 keylen,
                        *keybitsize = PKEY_SIZE_AES_192;
                else if (!t->plfver && t->wpllen == 640)
                        *keybitsize = PKEY_SIZE_AES_256;
-               rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
+               rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
                                   ZCRYPT_CEX6, AES_MK_SET,
                                   t->mkvp0, 0);
                if (!rc)
                        *flags = PKEY_FLAGS_MATCH_CUR_MKVP;
                if (rc == -ENODEV) {
-                       rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
+                       nr_apqns = ARRAY_SIZE(apqns);
+                       rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
                                           ZCRYPT_CEX6, AES_MK_SET,
                                           0, t->mkvp0);
                        if (!rc)
@@ -535,7 +535,6 @@ static int cca_verifykey(const u8 *key, u32 keylen,
        }
 
 out:
-       kfree(apqns);
        pr_debug("rc=%d\n", rc);
        return rc;
 }
index 1f4e14905ee5b8c35c0331a9962f7c254654b882..b2ad377e1877d79c8606a436a6d5697cb6d88f5d 100644 (file)
@@ -1698,13 +1698,13 @@ out:
 }
 EXPORT_SYMBOL(cca_get_info);
 
-int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
+int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
                  int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp)
 {
        struct zcrypt_device_status_ext *device_status;
-       u32 *_apqns = NULL, _nr_apqns = 0;
-       int i, card, dom, curmatch, oldmatch, rc;
+       int i, card, dom, curmatch, oldmatch;
        struct cca_info ci;
+       u32 _nr_apqns = 0;
 
        /* occupy the device status memory */
        mutex_lock(&dev_status_mem_mutex);
@@ -1716,13 +1716,6 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
                                      ZCRYPT_DEV_STATUS_CARD_MAX,
                                      ZCRYPT_DEV_STATUS_QUEUE_MAX);
 
-       /* allocate 1k space for up to 256 apqns */
-       _apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
-       if (!_apqns) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
        /* walk through all the crypto apqnss */
        for (i = 0; i < ZCRYPT_DEV_STATUS_ENTRIES; i++) {
                card = AP_QID_CARD(device_status[i].qid);
@@ -1770,26 +1763,16 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
                                continue;
                }
                /* apqn passed all filtering criterons, add to the array */
-               if (_nr_apqns < 256)
-                       _apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom);
+               if (_nr_apqns < *nr_apqns)
+                       apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom);
        }
 
-       /* nothing found ? */
-       if (!_nr_apqns) {
-               kfree(_apqns);
-               rc = -ENODEV;
-       } else {
-               /* no re-allocation, simple return the _apqns array */
-               *apqns = _apqns;
-               *nr_apqns = _nr_apqns;
-               rc = 0;
-       }
+       *nr_apqns = _nr_apqns;
 
-out:
        /* release the device status memory */
        mutex_unlock(&dev_status_mem_mutex);
 
-       return rc;
+       return _nr_apqns ? 0 : -ENODEV;
 }
 EXPORT_SYMBOL(cca_findcard2);
 
index cc7d362a2bada9c74786f556c4e409360ab10d48..ca41a675dd3b8d81b40400caffd9cc4b9950ef09 100644 (file)
@@ -217,14 +217,12 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
  * - if old_mkvp != 0 only apqns where old_mkvp == mkvp
  * The mktype determines which set of master keys to use:
  *   0 = AES_MK_SET - AES MK set, 1 = APKA MK_SET - APKA MK set
- * The array of apqn entries is allocated with kmalloc and returned in *apqns;
- * the number of apqns stored into the list is returned in *nr_apqns. One apqn
- * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and
- * may be casted to struct pkey_apqn. The return value is either 0 for success
- * or a negative errno value. If no apqn meeting the criteria is found,
- * -ENODEV is returned.
+ * The caller should set *nr_apqns to the nr of elements available in *apqns.
+ * On return *nr_apqns is then updated with the nr of apqns filled into *apqns.
+ * The return value is either 0 for success or a negative errno value.
+ * If no apqn meeting the criteria is found, -ENODEV is returned.
  */
-int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
+int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
                  int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp);
 
 #define AES_MK_SET  0