[PATCH v4 13/24] s390/zcrypt/pkey: Rework cca findcard() implementation and callers

Harald Freudenberger
2025-04-09T14:03:22Z

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>
---
drivers/s390/crypto/pkey_cca.c | 25 ++++++++++------------
drivers/s390/crypto/zcrypt_ccamisc.c | 31 +++++++---------------------
drivers/s390/crypto/zcrypt_ccamisc.h | 12 +++++------
3 files changed, 23 insertions(+), 45 deletions(-)

diff --git a/drivers/s390/crypto/pkey_cca.c b/drivers/s390/crypto/pkey_cca.c
index 83b02a466346..5b1f4c571c88 100644
--- a/drivers/s390/crypto/pkey_cca.c
+++ b/drivers/s390/crypto/pkey_cca.c
@@ -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,13 @@ 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,
+ rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX3C, AES_MK_SET,
0, t->mkvp);
if (!rc)
@@ -511,13 +509,13 @@ 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,
+ rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX6, AES_MK_SET,
0, t->mkvp0);
if (!rc)
@@ -535,7 +533,6 @@ static int cca_verifykey(const u8 *key, u32 keylen,
}

out:
- kfree(apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index 7e24b78d4e56..15731eb250fb 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -1707,13 +1707,13 @@ int cca_get_info(u16 card, u16 dom, struct cca_info *ci)
}
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);
@@ -1725,13 +1725,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);
@@ -1779,26 +1772,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);

diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h
index cc7d362a2bad..ca41a675dd3b 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.h
+++ b/drivers/s390/crypto/zcrypt_ccamisc.h
@@ -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
--
2.43.0