Commit 1bd47937 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Heiko Carstens
Browse files

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: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarHolger Dengler <dengler@linux.ibm.com>
Reviewed-by: default avatarSteffen Eiden <seiden@linux.ibm.com>
Link: https://lore.kernel.org/r/20250424133619.16495-23-freude@linux.ibm.com


Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 933dd21d
Loading
Loading
Loading
Loading
+35 −3
Original line number Diff line number Diff line
@@ -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);