From: Harald Freudenberger Date: Thu, 24 Apr 2025 13:36:16 +0000 (+0200) Subject: s390/pkey: Use preallocated memory for retrieve of UV secret metadata X-Git-Tag: v6.16-rc1~201^2~16^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1bd4793728c3d83452daf5ae2a6d22a9711070c3;p=thirdparty%2Fkernel%2Flinux.git s390/pkey: Use preallocated memory for retrieve of UV secret metadata The pkey uv functions may be called in a situation where memory allocations which trigger IO operations are not allowed. An example: decryption of the swap partition with protected key (PAES). The pkey uv code takes care of this by holding one preallocated struct uv_secret_list to be used with the new UV function uv_find_secret(). The older function uv_get_secret_metadata() used before always allocates/frees an ephemeral memory buffer. The preallocated struct is concurrency protected by a mutex. Signed-off-by: Harald Freudenberger Reviewed-by: Holger Dengler Reviewed-by: Steffen Eiden Link: https://lore.kernel.org/r/20250424133619.16495-23-freude@linux.ibm.com Signed-off-by: Heiko Carstens --- diff --git a/drivers/s390/crypto/pkey_uv.c b/drivers/s390/crypto/pkey_uv.c index 805817b143540..afbdb59c90f5a 100644 --- a/drivers/s390/crypto/pkey_uv.c +++ b/drivers/s390/crypto/pkey_uv.c @@ -20,6 +20,12 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("s390 protected key UV handler"); +/* + * One pre-allocated uv_secret_list for use with uv_find_secret() + */ +static struct uv_secret_list *uv_list; +static DEFINE_MUTEX(uv_list_mutex); + /* * UV secret token struct and defines. */ @@ -85,13 +91,26 @@ static bool is_uv_keytype(enum pkey_key_type keytype) } } +static int get_secret_metadata(const u8 secret_id[UV_SECRET_ID_LEN], + struct uv_secret_list_item_hdr *secret) +{ + int rc; + + mutex_lock(&uv_list_mutex); + memset(uv_list, 0, sizeof(*uv_list)); + rc = uv_find_secret(secret_id, uv_list, secret); + mutex_unlock(&uv_list_mutex); + + return rc; +} + static int retrieve_secret(const u8 secret_id[UV_SECRET_ID_LEN], u16 *secret_type, u8 *buf, u32 *buflen) { struct uv_secret_list_item_hdr secret_meta_data; int rc; - rc = uv_get_secret_metadata(secret_id, &secret_meta_data); + rc = get_secret_metadata(secret_id, &secret_meta_data); if (rc) return rc; @@ -225,7 +244,7 @@ static int uv_verifykey(const u8 *key, u32 keylen, if (rc) goto out; - rc = uv_get_secret_metadata(t->secret_id, &secret_meta_data); + rc = get_secret_metadata(t->secret_id, &secret_meta_data); if (rc) goto out; @@ -263,13 +282,23 @@ static struct pkey_handler uv_handler = { */ static int __init pkey_uv_init(void) { + int rc; + if (!is_prot_virt_guest()) return -ENODEV; if (!test_bit_inv(BIT_UVC_CMD_RETR_SECRET, uv_info.inst_calls_list)) return -ENODEV; - return pkey_handler_register(&uv_handler); + uv_list = kmalloc(sizeof(*uv_list), GFP_KERNEL); + if (!uv_list) + return -ENOMEM; + + rc = pkey_handler_register(&uv_handler); + if (rc) + kfree(uv_list); + + return rc; } /* @@ -278,6 +307,9 @@ static int __init pkey_uv_init(void) static void __exit pkey_uv_exit(void) { pkey_handler_unregister(&uv_handler); + mutex_lock(&uv_list_mutex); + kvfree(uv_list); + mutex_unlock(&uv_list_mutex); } module_cpu_feature_match(S390_CPU_FEATURE_UV, pkey_uv_init);