From c45dabf47e76cc60721301c4ee03926c52be49ca Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Thu, 24 Apr 2025 15:36:13 +0200 Subject: [PATCH] s390/pkey: Rework CCA pkey handler to use stack for small memory allocs There have been some places in the CCA handler code where relatively small amounts of memory have been allocated an freed at the end of the function. This code has been reworked to use the stack instead. Signed-off-by: Harald Freudenberger Reviewed-by: Holger Dengler Link: https://lore.kernel.org/r/20250424133619.16495-20-freude@linux.ibm.com Signed-off-by: Heiko Carstens --- drivers/s390/crypto/pkey_cca.c | 43 ++++++++-------------------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/drivers/s390/crypto/pkey_cca.c b/drivers/s390/crypto/pkey_cca.c index 50cbcb91565f..0cbb163c7df0 100644 --- a/drivers/s390/crypto/pkey_cca.c +++ b/drivers/s390/crypto/pkey_cca.c @@ -213,7 +213,7 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns, u8 *protkey, u32 *protkeylen, u32 *protkeytype) { struct keytoken_header *hdr = (struct keytoken_header *)key; - struct pkey_apqn *local_apqns = NULL; + struct pkey_apqn _apqns[MAXAPQNSINLIST]; int i, rc; if (keylen < sizeof(*hdr)) @@ -251,14 +251,10 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns, if (!apqns || (nr_apqns == 1 && apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { nr_apqns = MAXAPQNSINLIST; - local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), - GFP_KERNEL); - if (!local_apqns) - return -ENOMEM; - rc = cca_apqns4key(key, keylen, 0, local_apqns, &nr_apqns); + rc = cca_apqns4key(key, keylen, 0, _apqns, &nr_apqns); if (rc) goto out; - apqns = local_apqns; + apqns = _apqns; } for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { @@ -283,7 +279,6 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns, } out: - kfree(local_apqns); pr_debug("rc=%d\n", rc); return rc; } @@ -302,7 +297,7 @@ static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns, u32 keybitsize, u32 flags, u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) { - struct pkey_apqn *local_apqns = NULL; + struct pkey_apqn _apqns[MAXAPQNSINLIST]; int i, len, rc; /* check keytype, subtype, keybitsize */ @@ -338,15 +333,10 @@ static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns, if (!apqns || (nr_apqns == 1 && apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { nr_apqns = MAXAPQNSINLIST; - local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), - GFP_KERNEL); - if (!local_apqns) - return -ENOMEM; - rc = cca_apqns4type(subtype, NULL, NULL, 0, - local_apqns, &nr_apqns); + rc = cca_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns); if (rc) goto out; - apqns = local_apqns; + apqns = _apqns; } for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { @@ -363,7 +353,6 @@ static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns, } out: - kfree(local_apqns); pr_debug("rc=%d\n", rc); return rc; } @@ -383,7 +372,7 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns, const u8 *clrkey, u32 clrkeylen, u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) { - struct pkey_apqn *local_apqns = NULL; + struct pkey_apqn _apqns[MAXAPQNSINLIST]; int i, len, rc; /* check keytype, subtype, clrkeylen, keybitsize */ @@ -424,15 +413,10 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns, if (!apqns || (nr_apqns == 1 && apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { nr_apqns = MAXAPQNSINLIST; - local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), - GFP_KERNEL); - if (!local_apqns) - return -ENOMEM; - rc = cca_apqns4type(subtype, NULL, NULL, 0, - local_apqns, &nr_apqns); + rc = cca_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns); if (rc) goto out; - apqns = local_apqns; + apqns = _apqns; } for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { @@ -449,7 +433,6 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns, } out: - kfree(local_apqns); pr_debug("rc=%d\n", rc); return rc; } @@ -554,8 +537,8 @@ static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns, { const struct keytoken_header *hdr = (const struct keytoken_header *)key; const struct clearkeytoken *t = (const struct clearkeytoken *)key; + u8 tmpbuf[SECKEYBLOBSIZE]; /* 64 bytes */ u32 tmplen, keysize = 0; - u8 *tmpbuf; int i, rc; if (keylen < sizeof(*hdr)) @@ -567,11 +550,6 @@ static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns, if (!keysize || t->len != keysize) return -EINVAL; - /* alloc tmp key buffer */ - tmpbuf = kmalloc(SECKEYBLOBSIZE, GFP_ATOMIC); - if (!tmpbuf) - return -ENOMEM; - /* try two times in case of failure */ for (i = 0, rc = -ENODEV; i < 2 && rc; i++) { tmplen = SECKEYBLOBSIZE; @@ -586,7 +564,6 @@ static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns, pr_debug("cca_key2protkey()=%d\n", rc); } - kfree(tmpbuf); pr_debug("rc=%d\n", rc); return rc; } -- 2.25.1