From: Harald Freudenberger <freude@linux.ibm.com>
To: dengler@linux.ibm.com, fcallies@linux.ibm.com
Cc: freude@linux.ibm.com, linux-s390@vger.kernel.org,
Heiko Carstens <hca@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
Alexander Gordeev <agordeev@linux.ibm.com>
Subject: [PATCH v5 1/1] s390/zcrypt: Improve zcrypt reply message verification checks
Date: Fri, 10 Jul 2026 17:10:05 +0200 [thread overview]
Message-ID: <20260710151005.79765-2-freude@linux.ibm.com> (raw)
In-Reply-To: <20260710151005.79765-1-freude@linux.ibm.com>
Add or improve checks related to buffer sizes and reply sizes to the
handling of replies from the crypto cards for CCA and EP11 (AP message
type 6) messages. The verification code related to reply field length
was not designed well and thus firmware deficiencies could lead to
unexpected behavior in the zcrypt device driver. Thus improve the code
to more closely inspect especially length fields at message replies.
The 3 hunks of this patch deal with CCA, EP11 and (CCA) RNG replies
and improve the checking for reply buffer size by using size_t instead
of int. RNG replies an additional check makes sure the hard coded
limit of the data buffer is not exceeded. Also there was a condition
with additional data for an CCA reply where some of the field values
where unchecked used to invoke memcpy into user
space. zcrypt_msgtype6_receive() now checks all the relevant fields
before convert_type86_xcrb() uses them.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Cc: stable@vger.kernel.org
---
drivers/s390/crypto/zcrypt_msgtype6.c | 42 ++++++++++++++++++++++-----
1 file changed, 34 insertions(+), 8 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index 40f72cdf284d..8252fd185663 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -691,6 +691,13 @@ static int convert_type86_rng(struct zcrypt_queue *zq,
if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
return -EINVAL;
+ /*
+ * Note that offset2 and count2 have already been checked in
+ * zcrypt_msgtype6_receive(). So only check for not exceeding
+ * the hard coded rng buffer size.
+ */
+ if (msg->fmt2.count2 > ZCRYPT_RNG_BUFFER_SIZE)
+ return -EMSGSIZE;
memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
return msg->fmt2.count2;
}
@@ -853,7 +860,7 @@ static void zcrypt_msgtype6_receive(struct ap_queue *aq,
};
struct ap_response_type *resp_type = &msg->response;
struct type86x_reply *t86r;
- int len;
+ size_t len, len1, len2 = 0;
/* Copy the reply message to the request message buffer. */
if (!reply)
@@ -863,7 +870,8 @@ static void zcrypt_msgtype6_receive(struct ap_queue *aq,
t86r->cprbx.cprb_ver_id == 0x02) {
switch (resp_type->type) {
case CEXXC_RESPONSE_TYPE_ICA:
- len = sizeof(struct type86x_reply) + t86r->length;
+ len = (size_t)sizeof(struct type86x_reply) +
+ (size_t)t86r->length;
if (len > reply->bufsize || len > msg->bufsize ||
len != reply->len) {
pr_debug("len mismatch => EMSGSIZE\n");
@@ -874,10 +882,27 @@ static void zcrypt_msgtype6_receive(struct ap_queue *aq,
msg->len = len;
break;
case CEXXC_RESPONSE_TYPE_XCRB:
- if (t86r->fmt2.count2)
- len = t86r->fmt2.offset2 + t86r->fmt2.count2;
- else
- len = t86r->fmt2.offset1 + t86r->fmt2.count1;
+ len1 = (size_t)t86r->fmt2.offset1 +
+ (size_t)t86r->fmt2.count1;
+ if (t86r->fmt2.offset1 > reply->len ||
+ t86r->fmt2.count1 > reply->len ||
+ len1 > reply->len) {
+ pr_debug("len mismatch => EMSGSIZE\n");
+ msg->rc = -EMSGSIZE;
+ goto out;
+ }
+ if (t86r->fmt2.count2) {
+ len2 = (size_t)t86r->fmt2.offset2 +
+ (size_t)t86r->fmt2.count2;
+ if (t86r->fmt2.offset2 > reply->len ||
+ t86r->fmt2.count2 > reply->len ||
+ len2 > reply->len) {
+ pr_debug("len mismatch => EMSGSIZE\n");
+ msg->rc = -EMSGSIZE;
+ goto out;
+ }
+ }
+ len = max_t(size_t, len1, len2);
if (len > reply->bufsize || len > msg->bufsize ||
len != reply->len) {
pr_debug("len mismatch => EMSGSIZE\n");
@@ -917,7 +942,7 @@ static void zcrypt_msgtype6_receive_ep11(struct ap_queue *aq,
};
struct ap_response_type *resp_type = &msg->response;
struct type86_ep11_reply *t86r;
- int len;
+ size_t len;
/* Copy the reply message to the request message buffer. */
if (!reply)
@@ -927,7 +952,8 @@ static void zcrypt_msgtype6_receive_ep11(struct ap_queue *aq,
t86r->cprbx.cprb_ver_id == 0x04) {
switch (resp_type->type) {
case CEXXC_RESPONSE_TYPE_EP11:
- len = t86r->fmt2.offset1 + t86r->fmt2.count1;
+ len = (size_t)t86r->fmt2.offset1 +
+ (size_t)t86r->fmt2.count1;
if (len > reply->bufsize || len > msg->bufsize ||
len != reply->len) {
pr_debug("len mismatch => EMSGSIZE\n");
--
2.43.0
next prev parent reply other threads:[~2026-07-10 15:10 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-10 15:10 [PATCH v5 0/1] Improve zcrypt reply message verification checks Harald Freudenberger
2026-07-10 15:10 ` Harald Freudenberger [this message]
2026-07-10 15:29 ` [PATCH v5 1/1] s390/zcrypt: " sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260710151005.79765-2-freude@linux.ibm.com \
--to=freude@linux.ibm.com \
--cc=agordeev@linux.ibm.com \
--cc=dengler@linux.ibm.com \
--cc=fcallies@linux.ibm.com \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=linux-s390@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox