mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
s390/zcrypt: Introduce cprb mempool for cca misc functions
Introduce a new module parameter "zcrypt_mempool_threshold" for the zcrypt module. This parameter controls the minimal amount of mempool items which are pre-allocated for urgent requests/replies and will be used with the support for the new xflag ZCRYPT_XFLAG_NOMEMALLOC. The default value of 5 shall provide enough memory items to support up to 5 requests (and their associated reply) in parallel. The minimum value is 1 and is checked in zcrypt module init(). If the mempool is depleted upon one cca misc functions is called with the named xflag set, the function will fail with -ENOMEM and the caller is responsible for taking further actions. For CCA each mempool item is 16KB, as a CCA CPRB needs to hold the request and the reply. The pool items only support requests/replies with a limit of about 8KB. So by default the CCA mempool consumes 5 * 16KB = 80KB This is only part of an rework to support a new xflag ZCRYPT_XFLAG_NOMEMALLOC but not yet complete. 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-7-freude@linux.ibm.com Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
parent
80c20b2c6d
commit
9bdb5f7e83
|
|
@ -50,6 +50,10 @@ MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " \
|
|||
"Copyright IBM Corp. 2001, 2012");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
unsigned int zcrypt_mempool_threshold = 5;
|
||||
module_param_named(mempool_threshold, zcrypt_mempool_threshold, uint, 0440);
|
||||
MODULE_PARM_DESC(mempool_threshold, "CCA and EP11 request/reply mempool minimal items (min: 1)");
|
||||
|
||||
/*
|
||||
* zcrypt tracepoint functions
|
||||
*/
|
||||
|
|
@ -2144,13 +2148,23 @@ int __init zcrypt_api_init(void)
|
|||
{
|
||||
int rc;
|
||||
|
||||
/* make sure the mempool threshold is >= 1 */
|
||||
if (zcrypt_mempool_threshold < 1) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = zcrypt_debug_init();
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
rc = zcdn_init();
|
||||
if (rc)
|
||||
goto out;
|
||||
goto out_zcdn_init_failed;
|
||||
|
||||
rc = zcrypt_ccamisc_init();
|
||||
if (rc)
|
||||
goto out_ccamisc_init_failed;
|
||||
|
||||
/* Register the request sprayer. */
|
||||
rc = misc_register(&zcrypt_misc_device);
|
||||
|
|
@ -2163,7 +2177,10 @@ int __init zcrypt_api_init(void)
|
|||
return 0;
|
||||
|
||||
out_misc_register_failed:
|
||||
zcrypt_ccamisc_exit();
|
||||
out_ccamisc_init_failed:
|
||||
zcdn_exit();
|
||||
out_zcdn_init_failed:
|
||||
zcrypt_debug_exit();
|
||||
out:
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@ extern atomic_t zcrypt_rescan_req;
|
|||
extern spinlock_t zcrypt_list_lock;
|
||||
extern struct list_head zcrypt_card_list;
|
||||
|
||||
extern unsigned int zcrypt_mempool_threshold;
|
||||
|
||||
#define for_each_zcrypt_card(_zc) \
|
||||
list_for_each_entry(_zc, &zcrypt_card_list, list)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
|
|
@ -40,6 +41,16 @@ struct cca_info_list_entry {
|
|||
static LIST_HEAD(cca_info_list);
|
||||
static DEFINE_SPINLOCK(cca_info_list_lock);
|
||||
|
||||
/*
|
||||
* Cprb memory pool held for urgent cases where no memory
|
||||
* can be allocated via kmalloc. This pool is only used
|
||||
* when alloc_and_prep_cprbmem() is called with the xflag
|
||||
* ZCRYPT_XFLAG_NOMEMALLOC. The cprb memory needs to hold
|
||||
* space for request AND reply!
|
||||
*/
|
||||
#define CPRB_MEMPOOL_ITEM_SIZE (16 * 1024)
|
||||
static mempool_t *cprb_mempool;
|
||||
|
||||
/*
|
||||
* Simple check if the token is a valid CCA secure AES data key
|
||||
* token. If keybitsize is given, the bitsize of the key is
|
||||
|
|
@ -219,19 +230,27 @@ EXPORT_SYMBOL(cca_check_sececckeytoken);
|
|||
static int alloc_and_prep_cprbmem(size_t paramblen,
|
||||
u8 **p_cprb_mem,
|
||||
struct CPRBX **p_req_cprb,
|
||||
struct CPRBX **p_rep_cprb)
|
||||
struct CPRBX **p_rep_cprb,
|
||||
u32 xflags)
|
||||
{
|
||||
u8 *cprbmem;
|
||||
u8 *cprbmem = NULL;
|
||||
size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen;
|
||||
size_t len = 2 * cprbplusparamblen;
|
||||
struct CPRBX *preqcblk, *prepcblk;
|
||||
|
||||
/*
|
||||
* allocate consecutive memory for request CPRB, request param
|
||||
* block, reply CPRB and reply param block
|
||||
*/
|
||||
cprbmem = kcalloc(2, cprbplusparamblen, GFP_KERNEL);
|
||||
if (xflags & ZCRYPT_XFLAG_NOMEMALLOC) {
|
||||
if (len <= CPRB_MEMPOOL_ITEM_SIZE)
|
||||
cprbmem = mempool_alloc_preallocated(cprb_mempool);
|
||||
} else {
|
||||
cprbmem = kmalloc(len, GFP_KERNEL);
|
||||
}
|
||||
if (!cprbmem)
|
||||
return -ENOMEM;
|
||||
memset(cprbmem, 0, len);
|
||||
|
||||
preqcblk = (struct CPRBX *)cprbmem;
|
||||
prepcblk = (struct CPRBX *)(cprbmem + cprbplusparamblen);
|
||||
|
|
@ -261,11 +280,15 @@ static int alloc_and_prep_cprbmem(size_t paramblen,
|
|||
* with zeros before freeing (useful if there was some
|
||||
* clear key material in there).
|
||||
*/
|
||||
static void free_cprbmem(void *mem, size_t paramblen, int scrub)
|
||||
static void free_cprbmem(void *mem, size_t paramblen, bool scrub, u32 xflags)
|
||||
{
|
||||
if (scrub)
|
||||
if (mem && scrub)
|
||||
memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen));
|
||||
kfree(mem);
|
||||
|
||||
if (xflags & ZCRYPT_XFLAG_NOMEMALLOC)
|
||||
mempool_free(mem, cprb_mempool);
|
||||
else
|
||||
kfree(mem);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -330,9 +353,11 @@ int cca_genseckey(u16 cardnr, u16 domain,
|
|||
} keyblock;
|
||||
} lv3;
|
||||
} __packed * prepparm;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* get already prepared memory for 2 cprbs with param block each */
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
|
||||
&preqcblk, &prepcblk, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -379,7 +404,7 @@ int cca_genseckey(u16 cardnr, u16 domain,
|
|||
prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
|
||||
|
||||
/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
|
||||
rc = zcrypt_send_cprb(&xcrb, 0);
|
||||
rc = zcrypt_send_cprb(&xcrb, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, errno %d\n",
|
||||
__func__, (int)cardnr, (int)domain, rc);
|
||||
|
|
@ -424,7 +449,7 @@ int cca_genseckey(u16 cardnr, u16 domain,
|
|||
memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE);
|
||||
|
||||
out:
|
||||
free_cprbmem(mem, PARMBSIZE, 0);
|
||||
free_cprbmem(mem, PARMBSIZE, false, xflags);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(cca_genseckey);
|
||||
|
|
@ -471,9 +496,11 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
|
|||
} keyblock;
|
||||
} lv3;
|
||||
} __packed * prepparm;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* get already prepared memory for 2 cprbs with param block each */
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
|
||||
&preqcblk, &prepcblk, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -517,7 +544,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
|
|||
prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
|
||||
|
||||
/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
|
||||
rc = zcrypt_send_cprb(&xcrb, 0);
|
||||
rc = zcrypt_send_cprb(&xcrb, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
|
||||
__func__, (int)cardnr, (int)domain, rc);
|
||||
|
|
@ -563,7 +590,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
|
|||
memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE);
|
||||
|
||||
out:
|
||||
free_cprbmem(mem, PARMBSIZE, 1);
|
||||
free_cprbmem(mem, PARMBSIZE, true, xflags);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(cca_clr2seckey);
|
||||
|
|
@ -617,9 +644,11 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
|
|||
} ckb;
|
||||
} lv3;
|
||||
} __packed * prepparm;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* get already prepared memory for 2 cprbs with param block each */
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
|
||||
&preqcblk, &prepcblk, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -644,7 +673,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
|
|||
prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
|
||||
|
||||
/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
|
||||
rc = zcrypt_send_cprb(&xcrb, 0);
|
||||
rc = zcrypt_send_cprb(&xcrb, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
|
||||
__func__, (int)cardnr, (int)domain, rc);
|
||||
|
|
@ -712,7 +741,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
|
|||
*protkeylen = prepparm->lv3.ckb.len;
|
||||
|
||||
out:
|
||||
free_cprbmem(mem, PARMBSIZE, 0);
|
||||
free_cprbmem(mem, PARMBSIZE, true, xflags);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(cca_sec2protkey);
|
||||
|
|
@ -811,9 +840,11 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
} kb;
|
||||
} __packed * prepparm;
|
||||
struct cipherkeytoken *t;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* get already prepared memory for 2 cprbs with param block each */
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
|
||||
&preqcblk, &prepcblk, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -872,7 +903,7 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
|
||||
|
||||
/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
|
||||
rc = zcrypt_send_cprb(&xcrb, 0);
|
||||
rc = zcrypt_send_cprb(&xcrb, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
|
||||
__func__, (int)cardnr, (int)domain, rc);
|
||||
|
|
@ -923,7 +954,7 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
*keybufsize = t->len;
|
||||
|
||||
out:
|
||||
free_cprbmem(mem, PARMBSIZE, 0);
|
||||
free_cprbmem(mem, PARMBSIZE, false, xflags);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(cca_gencipherkey);
|
||||
|
|
@ -987,9 +1018,11 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
|
|||
} __packed * prepparm;
|
||||
struct cipherkeytoken *t;
|
||||
int complete = strncmp(rule_array_2, "COMPLETE", 8) ? 0 : 1;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* get already prepared memory for 2 cprbs with param block each */
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
|
||||
&preqcblk, &prepcblk, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -1038,7 +1071,7 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
|
|||
prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
|
||||
|
||||
/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
|
||||
rc = zcrypt_send_cprb(&xcrb, 0);
|
||||
rc = zcrypt_send_cprb(&xcrb, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
|
||||
__func__, (int)cardnr, (int)domain, rc);
|
||||
|
|
@ -1077,7 +1110,7 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
|
|||
*key_token_size = t->len;
|
||||
|
||||
out:
|
||||
free_cprbmem(mem, PARMBSIZE, 0);
|
||||
free_cprbmem(mem, PARMBSIZE, false, xflags);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -1217,9 +1250,11 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
|
|||
} kb;
|
||||
} __packed * prepparm;
|
||||
int keytoklen = ((struct cipherkeytoken *)ckey)->len;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* get already prepared memory for 2 cprbs with param block each */
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
|
||||
&preqcblk, &prepcblk, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -1249,7 +1284,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
|
|||
prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
|
||||
|
||||
/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
|
||||
rc = zcrypt_send_cprb(&xcrb, 0);
|
||||
rc = zcrypt_send_cprb(&xcrb, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
|
||||
__func__, (int)cardnr, (int)domain, rc);
|
||||
|
|
@ -1323,7 +1358,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
|
|||
*protkeylen = prepparm->vud.ckb.keylen;
|
||||
|
||||
out:
|
||||
free_cprbmem(mem, PARMBSIZE, 0);
|
||||
free_cprbmem(mem, PARMBSIZE, true, xflags);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(cca_cipher2protkey);
|
||||
|
|
@ -1380,9 +1415,11 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
|
|||
/* followed by a key block */
|
||||
} __packed * prepparm;
|
||||
int keylen = ((struct eccprivkeytoken *)key)->len;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* get already prepared memory for 2 cprbs with param block each */
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
|
||||
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
|
||||
&preqcblk, &prepcblk, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -1412,7 +1449,7 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
|
|||
prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
|
||||
|
||||
/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
|
||||
rc = zcrypt_send_cprb(&xcrb, 0);
|
||||
rc = zcrypt_send_cprb(&xcrb, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
|
||||
__func__, (int)cardnr, (int)domain, rc);
|
||||
|
|
@ -1470,7 +1507,7 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
|
|||
*protkeytype = PKEY_KEYTYPE_ECC;
|
||||
|
||||
out:
|
||||
free_cprbmem(mem, PARMBSIZE, 0);
|
||||
free_cprbmem(mem, PARMBSIZE, true, xflags);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(cca_ecc2protkey);
|
||||
|
|
@ -1503,9 +1540,11 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
|
|||
u8 subfunc_code[2];
|
||||
u8 lvdata[];
|
||||
} __packed * prepparm;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* get already prepared memory for 2 cprbs with param block each */
|
||||
rc = alloc_and_prep_cprbmem(parmbsize, &mem, &preqcblk, &prepcblk);
|
||||
rc = alloc_and_prep_cprbmem(parmbsize, &mem,
|
||||
&preqcblk, &prepcblk, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -1526,7 +1565,7 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
|
|||
prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
|
||||
|
||||
/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
|
||||
rc = zcrypt_send_cprb(&xcrb, 0);
|
||||
rc = zcrypt_send_cprb(&xcrb, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
|
||||
__func__, (int)cardnr, (int)domain, rc);
|
||||
|
|
@ -1573,7 +1612,7 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
|
|||
}
|
||||
|
||||
out:
|
||||
free_cprbmem(mem, parmbsize, 0);
|
||||
free_cprbmem(mem, parmbsize, false, xflags);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(cca_query_crypto_facility);
|
||||
|
|
@ -1959,7 +1998,19 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
|
|||
}
|
||||
EXPORT_SYMBOL(cca_findcard2);
|
||||
|
||||
void __exit zcrypt_ccamisc_exit(void)
|
||||
int __init zcrypt_ccamisc_init(void)
|
||||
{
|
||||
/* Pre-allocate a small memory pool for cca cprbs. */
|
||||
cprb_mempool = mempool_create_kmalloc_pool(zcrypt_mempool_threshold,
|
||||
CPRB_MEMPOOL_ITEM_SIZE);
|
||||
if (!cprb_mempool)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zcrypt_ccamisc_exit(void)
|
||||
{
|
||||
mkvp_cache_free();
|
||||
mempool_destroy(cprb_mempool);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ struct cca_info {
|
|||
*/
|
||||
int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify);
|
||||
|
||||
int zcrypt_ccamisc_init(void);
|
||||
void zcrypt_ccamisc_exit(void);
|
||||
|
||||
#endif /* _ZCRYPT_CCAMISC_H_ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user