Skip to content

Commit e75003a

Browse files
committed
Merge branch 'zcrypt-no-alloc'
Harald Freudenberger says: ==================== This series of patches has the goal to open up a do-not-allocate memory path from the callers of the pkey in-kernel api down to the crypto cards and back. The asynch in-kernel cipher implementations (and the s390 PAES cipher implementations are one of them) may be called in a context where memory allocations which trigger IO is not acceptable. So this patch series reworks the AP bus code, the zcrypt layer, the pkey layer and the pkey handlers to respect this situation by processing a new parameter xflags (execution hints flags). There is a flag PKEY_XFLAG_NOMEMALLOC which tells the code to not allocate memory which may lead to IO operations. To reach this goal, the actual code changes have been differed. The zcrypt misc functions which need memory for cprb build use a pre allocated memory pool for this purpose. The findcard() functions have one temp memory area preallocated and protected with a mutex. Some smaller data is not allocated any more but went to the stack instead. The AP bus also uses a pre-allocated memory pool for building AP message requests. Note that the PAES implementation still needs to get reworked to run the protected key derivation in a real asynchronous way. However, this rework of AP bus, zcrypt and pkey is the base work required before reconsidering the PAES implementation. The patch series starts bottom (AP bus) and goes up the call chain (PKEY). At any time in the patch stack it should compile. For easier review I tried to have one logic code change by each patch and thus keep the patches "small". ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Heiko Carstens <[email protected]>
2 parents 7cf5888 + f688429 commit e75003a

23 files changed

+963
-1028
lines changed

arch/s390/crypto/paes_s390.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,14 @@ static inline int __paes_keyblob2pkey(const u8 *key, unsigned int keylen,
182182
{
183183
int i, rc = -EIO;
184184

185-
/* try three times in case of busy card */
185+
/* try three times in case of busy card or no mem */
186186
for (i = 0; rc && i < 3; i++) {
187-
if (rc == -EBUSY && in_task()) {
187+
if ((rc == -EBUSY || rc == -ENOMEM) && in_task()) {
188188
if (msleep_interruptible(1000))
189189
return -EINTR;
190190
}
191191
rc = pkey_key2protkey(key, keylen, pk->protkey, &pk->len,
192-
&pk->type);
192+
&pk->type, PKEY_XFLAG_NOMEMALLOC);
193193
}
194194

195195
return rc;

arch/s390/include/asm/pkey.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,22 @@
2020
* @param key pointer to a buffer containing the key blob
2121
* @param keylen size of the key blob in bytes
2222
* @param protkey pointer to buffer receiving the protected key
23+
* @param xflags additional execution flags (see PKEY_XFLAG_* definitions below)
24+
* As of now the only supported flag is PKEY_XFLAG_NOMEMALLOC.
2325
* @return 0 on success, negative errno value on failure
2426
*/
2527
int pkey_key2protkey(const u8 *key, u32 keylen,
26-
u8 *protkey, u32 *protkeylen, u32 *protkeytype);
28+
u8 *protkey, u32 *protkeylen, u32 *protkeytype,
29+
u32 xflags);
30+
31+
/*
32+
* If this flag is given in the xflags parameter, the pkey implementation
33+
* is not allowed to allocate memory but instead should fall back to use
34+
* preallocated memory or simple fail with -ENOMEM.
35+
* This flag is for protected key derive within a cipher or similar
36+
* which must not allocate memory which would cause io operations - see
37+
* also the CRYPTO_ALG_ALLOCATES_MEMORY flag in crypto.h.
38+
*/
39+
#define PKEY_XFLAG_NOMEMALLOC 0x0001
2740

2841
#endif /* _KAPI_PKEY_H */

arch/s390/include/asm/uv.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -616,8 +616,9 @@ static inline int uv_remove_shared(unsigned long addr)
616616
return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS);
617617
}
618618

619-
int uv_get_secret_metadata(const u8 secret_id[UV_SECRET_ID_LEN],
620-
struct uv_secret_list_item_hdr *secret);
619+
int uv_find_secret(const u8 secret_id[UV_SECRET_ID_LEN],
620+
struct uv_secret_list *list,
621+
struct uv_secret_list_item_hdr *secret);
621622
int uv_retrieve_secret(u16 secret_idx, u8 *buf, size_t buf_size);
622623

623624
extern int prot_virt_host;

arch/s390/kernel/uv.c

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,12 @@ static int __init uv_sysfs_init(void)
782782
device_initcall(uv_sysfs_init);
783783

784784
/*
785-
* Find the secret with the secret_id in the provided list.
785+
* Locate a secret in the list by its id.
786+
* @secret_id: search pattern.
787+
* @list: ephemeral buffer space
788+
* @secret: output data, containing the secret's metadata.
789+
*
790+
* Search for a secret with the given secret_id in the Ultravisor secret store.
786791
*
787792
* Context: might sleep.
788793
*/
@@ -803,12 +808,15 @@ static int find_secret_in_page(const u8 secret_id[UV_SECRET_ID_LEN],
803808

804809
/*
805810
* Do the actual search for `uv_get_secret_metadata`.
811+
* @secret_id: search pattern.
812+
* @list: ephemeral buffer space
813+
* @secret: output data, containing the secret's metadata.
806814
*
807815
* Context: might sleep.
808816
*/
809-
static int find_secret(const u8 secret_id[UV_SECRET_ID_LEN],
810-
struct uv_secret_list *list,
811-
struct uv_secret_list_item_hdr *secret)
817+
int uv_find_secret(const u8 secret_id[UV_SECRET_ID_LEN],
818+
struct uv_secret_list *list,
819+
struct uv_secret_list_item_hdr *secret)
812820
{
813821
u16 start_idx = 0;
814822
u16 list_rc;
@@ -830,36 +838,7 @@ static int find_secret(const u8 secret_id[UV_SECRET_ID_LEN],
830838

831839
return -ENOENT;
832840
}
833-
834-
/**
835-
* uv_get_secret_metadata() - get secret metadata for a given secret id.
836-
* @secret_id: search pattern.
837-
* @secret: output data, containing the secret's metadata.
838-
*
839-
* Search for a secret with the given secret_id in the Ultravisor secret store.
840-
*
841-
* Context: might sleep.
842-
*
843-
* Return:
844-
* * %0: - Found entry; secret->idx and secret->type are valid.
845-
* * %ENOENT - No entry found.
846-
* * %ENODEV: - Not supported: UV not available or command not available.
847-
* * %EIO: - Other unexpected UV error.
848-
*/
849-
int uv_get_secret_metadata(const u8 secret_id[UV_SECRET_ID_LEN],
850-
struct uv_secret_list_item_hdr *secret)
851-
{
852-
struct uv_secret_list *buf;
853-
int rc;
854-
855-
buf = kzalloc(sizeof(*buf), GFP_KERNEL);
856-
if (!buf)
857-
return -ENOMEM;
858-
rc = find_secret(secret_id, buf, secret);
859-
kfree(buf);
860-
return rc;
861-
}
862-
EXPORT_SYMBOL_GPL(uv_get_secret_metadata);
841+
EXPORT_SYMBOL_GPL(uv_find_secret);
863842

864843
/**
865844
* uv_retrieve_secret() - get the secret value for the secret index.

drivers/s390/crypto/ap_bus.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/module.h>
4242
#include <asm/uv.h>
4343
#include <asm/chsc.h>
44+
#include <linux/mempool.h>
4445

4546
#include "ap_bus.h"
4647
#include "ap_debug.h"
@@ -102,6 +103,27 @@ static struct ap_config_info *const ap_qci_info_old = &qci[1];
102103
*/
103104
debug_info_t *ap_dbf_info;
104105

106+
/*
107+
* There is a need for a do-not-allocate-memory path through the AP bus
108+
* layer. The pkey layer may be triggered via the in-kernel interface from
109+
* a protected key crypto algorithm (namely PAES) to convert a secure key
110+
* into a protected key. This happens in a workqueue context, so sleeping
111+
* is allowed but memory allocations causing IO operations are not permitted.
112+
* To accomplish this, an AP message memory pool with pre-allocated space
113+
* is established. When ap_init_apmsg() with use_mempool set to true is
114+
* called, instead of kmalloc() the ap message buffer is allocated from
115+
* the ap_msg_pool. This pool only holds a limited amount of buffers:
116+
* ap_msg_pool_min_items with the item size AP_DEFAULT_MAX_MSG_SIZE and
117+
* exactly one of these items (if available) is returned if ap_init_apmsg()
118+
* with the use_mempool arg set to true is called. When this pool is exhausted
119+
* and use_mempool is set true, ap_init_apmsg() returns -ENOMEM without
120+
* any attempt to allocate memory and the caller has to deal with that.
121+
*/
122+
static mempool_t *ap_msg_pool;
123+
static unsigned int ap_msg_pool_min_items = 8;
124+
module_param_named(msgpool_min_items, ap_msg_pool_min_items, uint, 0440);
125+
MODULE_PARM_DESC(msgpool_min_items, "AP message pool minimal items");
126+
105127
/*
106128
* AP bus rescan related things.
107129
*/
@@ -547,6 +569,48 @@ static void ap_poll_thread_stop(void)
547569
#define is_card_dev(x) ((x)->parent == ap_root_device)
548570
#define is_queue_dev(x) ((x)->parent != ap_root_device)
549571

572+
/*
573+
* ap_init_apmsg() - Initialize ap_message.
574+
*/
575+
int ap_init_apmsg(struct ap_message *ap_msg, u32 flags)
576+
{
577+
unsigned int maxmsgsize;
578+
579+
memset(ap_msg, 0, sizeof(*ap_msg));
580+
ap_msg->flags = flags;
581+
582+
if (flags & AP_MSG_FLAG_MEMPOOL) {
583+
ap_msg->msg = mempool_alloc_preallocated(ap_msg_pool);
584+
if (!ap_msg->msg)
585+
return -ENOMEM;
586+
ap_msg->bufsize = AP_DEFAULT_MAX_MSG_SIZE;
587+
return 0;
588+
}
589+
590+
maxmsgsize = atomic_read(&ap_max_msg_size);
591+
ap_msg->msg = kmalloc(maxmsgsize, GFP_KERNEL);
592+
if (!ap_msg->msg)
593+
return -ENOMEM;
594+
ap_msg->bufsize = maxmsgsize;
595+
596+
return 0;
597+
}
598+
EXPORT_SYMBOL(ap_init_apmsg);
599+
600+
/*
601+
* ap_release_apmsg() - Release ap_message.
602+
*/
603+
void ap_release_apmsg(struct ap_message *ap_msg)
604+
{
605+
if (ap_msg->flags & AP_MSG_FLAG_MEMPOOL) {
606+
memzero_explicit(ap_msg->msg, ap_msg->bufsize);
607+
mempool_free(ap_msg->msg, ap_msg_pool);
608+
} else {
609+
kfree_sensitive(ap_msg->msg);
610+
}
611+
}
612+
EXPORT_SYMBOL(ap_release_apmsg);
613+
550614
/**
551615
* ap_bus_match()
552616
* @dev: Pointer to device
@@ -2431,6 +2495,14 @@ static int __init ap_module_init(void)
24312495
/* init ap_queue hashtable */
24322496
hash_init(ap_queues);
24332497

2498+
/* create ap msg buffer memory pool */
2499+
ap_msg_pool = mempool_create_kmalloc_pool(ap_msg_pool_min_items,
2500+
AP_DEFAULT_MAX_MSG_SIZE);
2501+
if (!ap_msg_pool) {
2502+
rc = -ENOMEM;
2503+
goto out;
2504+
}
2505+
24342506
/* set up the AP permissions (ioctls, ap and aq masks) */
24352507
ap_perms_init();
24362508

@@ -2477,6 +2549,7 @@ static int __init ap_module_init(void)
24772549
out_bus:
24782550
bus_unregister(&ap_bus_type);
24792551
out:
2552+
mempool_destroy(ap_msg_pool);
24802553
ap_debug_exit();
24812554
return rc;
24822555
}
@@ -2487,6 +2560,7 @@ static void __exit ap_module_exit(void)
24872560
ap_irq_exit();
24882561
root_device_unregister(ap_root_device);
24892562
bus_unregister(&ap_bus_type);
2563+
mempool_destroy(ap_msg_pool);
24902564
ap_debug_exit();
24912565
}
24922566

drivers/s390/crypto/ap_bus.h

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ struct ap_queue {
214214

215215
typedef enum ap_sm_wait (ap_func_t)(struct ap_queue *queue);
216216

217+
struct ap_response_type {
218+
struct completion work;
219+
int type;
220+
};
221+
217222
struct ap_message {
218223
struct list_head list; /* Request queueing. */
219224
unsigned long psmid; /* Message id. */
@@ -222,7 +227,7 @@ struct ap_message {
222227
size_t bufsize; /* allocated msg buffer size */
223228
u16 flags; /* Flags, see AP_MSG_FLAG_xxx */
224229
int rc; /* Return code for this message */
225-
void *private; /* ap driver private pointer. */
230+
struct ap_response_type response;
226231
/* receive is called from tasklet context */
227232
void (*receive)(struct ap_queue *, struct ap_message *,
228233
struct ap_message *);
@@ -231,27 +236,10 @@ struct ap_message {
231236
#define AP_MSG_FLAG_SPECIAL 0x0001 /* flag msg as 'special' with NQAP */
232237
#define AP_MSG_FLAG_USAGE 0x0002 /* CCA, EP11: usage (no admin) msg */
233238
#define AP_MSG_FLAG_ADMIN 0x0004 /* CCA, EP11: admin (=control) msg */
239+
#define AP_MSG_FLAG_MEMPOOL 0x0008 /* ap msg buffer allocated via mempool */
234240

235-
/**
236-
* ap_init_message() - Initialize ap_message.
237-
* Initialize a message before using. Otherwise this might result in
238-
* unexpected behaviour.
239-
*/
240-
static inline void ap_init_message(struct ap_message *ap_msg)
241-
{
242-
memset(ap_msg, 0, sizeof(*ap_msg));
243-
}
244-
245-
/**
246-
* ap_release_message() - Release ap_message.
247-
* Releases all memory used internal within the ap_message struct
248-
* Currently this is the message and private field.
249-
*/
250-
static inline void ap_release_message(struct ap_message *ap_msg)
251-
{
252-
kfree_sensitive(ap_msg->msg);
253-
kfree_sensitive(ap_msg->private);
254-
}
241+
int ap_init_apmsg(struct ap_message *ap_msg, u32 flags);
242+
void ap_release_apmsg(struct ap_message *ap_msg);
255243

256244
enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event);
257245
enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event);

0 commit comments

Comments
 (0)