aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/crypto/zcrypt_msgtype6.c
diff options
context:
space:
mode:
authorHarald Freudenberger <freude@de.ibm.com>2018-05-28 13:00:42 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2018-05-30 11:18:05 +0200
commit89a0c0ec0d2e3ce0ee9caa00f60c0c26ccf11c21 (patch)
tree7e784683c6cb778d43b8b7fb4b3e73a78c19e533 /drivers/s390/crypto/zcrypt_msgtype6.c
parents390/archrandom: Rework arch random implementation. (diff)
downloadlinux-dev-89a0c0ec0d2e3ce0ee9caa00f60c0c26ccf11c21.tar.xz
linux-dev-89a0c0ec0d2e3ce0ee9caa00f60c0c26ccf11c21.zip
s390/zcrypt: Fix CCA and EP11 CPRB processing failure memory leak.
Tests showed, that the zcrypt device driver produces memory leaks when a valid CCA or EP11 CPRB can't get delivered or has a failure during processing within the zcrypt device driver. This happens when a invalid domain or adapter number is used or the lower level software or hardware layers produce any kind of failure during processing of the request. Only CPRBs send to CCA or EP11 cards can produce this memory leak. The accelerator and the CPRBs processed by this type of crypto card is not affected. The two fields message and private within the ap_message struct are allocated with pulling the function code for the CPRB but only freed when processing of the CPRB succeeds. So for example an invalid domain or adapter field causes the processing to fail, leaving these two memory areas allocated forever. Signed-off-by: Harald Freudenberger <freude@de.ibm.com> Reviewed-by: Ingo Franzki <ifranzki@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/crypto/zcrypt_msgtype6.c')
-rw-r--r--drivers/s390/crypto/zcrypt_msgtype6.c51
1 files changed, 19 insertions, 32 deletions
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index f54bef4a928e..97d4bacbc442 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -1084,6 +1084,13 @@ out_free:
return rc;
}
+/**
+ * Fetch function code from cprb.
+ * Extracting the fc requires to copy the cprb from userspace.
+ * So this function allocates memory and needs an ap_msg prepared
+ * by the caller with ap_init_message(). Also the caller has to
+ * make sure ap_release_message() is always called even on failure.
+ */
unsigned int get_cprb_fc(struct ica_xcRB *xcRB,
struct ap_message *ap_msg,
unsigned int *func_code, unsigned short **dom)
@@ -1091,9 +1098,7 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB,
struct response_type resp_type = {
.type = PCIXCC_RESPONSE_TYPE_XCRB,
};
- int rc;
- ap_init_message(ap_msg);
ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
if (!ap_msg->message)
return -ENOMEM;
@@ -1101,17 +1106,10 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB,
ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL);
- if (!ap_msg->private) {
- kzfree(ap_msg->message);
+ if (!ap_msg->private)
return -ENOMEM;
- }
memcpy(ap_msg->private, &resp_type, sizeof(resp_type));
- rc = XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code, dom);
- if (rc) {
- kzfree(ap_msg->message);
- kzfree(ap_msg->private);
- }
- return rc;
+ return XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code, dom);
}
/**
@@ -1139,11 +1137,16 @@ static long zcrypt_msgtype6_send_cprb(struct zcrypt_queue *zq,
/* Signal pending. */
ap_cancel_message(zq->queue, ap_msg);
- kzfree(ap_msg->message);
- kzfree(ap_msg->private);
return rc;
}
+/**
+ * Fetch function code from ep11 cprb.
+ * Extracting the fc requires to copy the ep11 cprb from userspace.
+ * So this function allocates memory and needs an ap_msg prepared
+ * by the caller with ap_init_message(). Also the caller has to
+ * make sure ap_release_message() is always called even on failure.
+ */
unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb,
struct ap_message *ap_msg,
unsigned int *func_code)
@@ -1151,9 +1154,7 @@ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb,
struct response_type resp_type = {
.type = PCIXCC_RESPONSE_TYPE_EP11,
};
- int rc;
- ap_init_message(ap_msg);
ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
if (!ap_msg->message)
return -ENOMEM;
@@ -1161,17 +1162,10 @@ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb,
ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL);
- if (!ap_msg->private) {
- kzfree(ap_msg->message);
+ if (!ap_msg->private)
return -ENOMEM;
- }
memcpy(ap_msg->private, &resp_type, sizeof(resp_type));
- rc = xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code);
- if (rc) {
- kzfree(ap_msg->message);
- kzfree(ap_msg->private);
- }
- return rc;
+ return xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code);
}
/**
@@ -1246,8 +1240,6 @@ static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_queue *zq,
/* Signal pending. */
ap_cancel_message(zq->queue, ap_msg);
- kzfree(ap_msg->message);
- kzfree(ap_msg->private);
return rc;
}
@@ -1258,7 +1250,6 @@ unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code,
.type = PCIXCC_RESPONSE_TYPE_XCRB,
};
- ap_init_message(ap_msg);
ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
if (!ap_msg->message)
return -ENOMEM;
@@ -1266,10 +1257,8 @@ unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code,
ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL);
- if (!ap_msg->private) {
- kzfree(ap_msg->message);
+ if (!ap_msg->private)
return -ENOMEM;
- }
memcpy(ap_msg->private, &resp_type, sizeof(resp_type));
rng_type6CPRB_msgX(ap_msg, ZCRYPT_RNG_BUFFER_SIZE, domain);
@@ -1313,8 +1302,6 @@ static long zcrypt_msgtype6_rng(struct zcrypt_queue *zq,
/* Signal pending. */
ap_cancel_message(zq->queue, ap_msg);
- kzfree(ap_msg->message);
- kzfree(ap_msg->private);
return rc;
}