* [PATCH v4 0/2] Improve code in zcrypt msg type 6 handling
@ 2026-07-24 13:45 Harald Freudenberger
2026-07-24 13:45 ` [PATCH v4 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger
2026-07-24 13:45 ` [PATCH v4 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger
0 siblings, 2 replies; 5+ messages in thread
From: Harald Freudenberger @ 2026-07-24 13:45 UTC (permalink / raw)
To: dengler, fcallies
Cc: freude, linux-s390, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev
Rework the limit and overflow checks in the both functions
xcrb_msg_to_type6_ep11cprb_msgx() and xcrb_msg_to_type6cprb_msgx().
Changelog:
v1: initial version, one patch dealing with overflow checks around
the use of the CEIL4 macro in zcrypt_msgtype6.c
v2: Sashiko found a regression: The check
if (ap_msg->len > ap_msg->bufsize)
was missing in the rework. Added again this important check.
v3: - Split into two patches - one for CCA one for EP11
- rework upper limit/overflow check
- add lower limit check
v4: - tried to address all the remaining complains from sashiko.
Harald Freudenberger (2):
s390/zcrypt: Improve CCA CPRB length and overflow checks
s390/zcrypt: Improve EP11 CPRB length and overflow checks
drivers/s390/crypto/zcrypt_msgtype6.c | 97 ++++++++++++++-------------
1 file changed, 51 insertions(+), 46 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks
2026-07-24 13:45 [PATCH v4 0/2] Improve code in zcrypt msg type 6 handling Harald Freudenberger
@ 2026-07-24 13:45 ` Harald Freudenberger
2026-07-24 14:21 ` sashiko-bot
2026-07-24 13:45 ` [PATCH v4 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger
1 sibling, 1 reply; 5+ messages in thread
From: Harald Freudenberger @ 2026-07-24 13:45 UTC (permalink / raw)
To: dengler, fcallies
Cc: freude, linux-s390, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev
The xcrb_msg_to_type6cprb_msgx() function lacks proper input
validation, creating security vulnerabilities:
1. Integer overflow after CEIL4 alignment: Signed int variables could
overflow during 4-byte boundary alignment, causing undersized
buffer allocations or incorrect bounds checking.
2. Missing minimum size validation: The CPRBX structure is copied from
userspace without verifying sufficient buffer length. Undersized
buffers cause uninitialized memory access when reading structure
fields like cprbx.cprb_len and cprbx.domain.
3. Arithmetic overflow in sum calculations: Adding control block and
data block sizes could overflow, bypassing size checks and enabling
buffer overflows.
4. Potential kernel memory leak if copy_from_user() only copies
xcrb->request_control_blk_length bytes but the processing of the
message works with the rounded up to 4 byte boundary buffer size.
Fix by using size_t for length calculations, adding U32_MAX boundary
checks after alignment, validating minimum control block size before
copying from userspace, and detecting sum calculation overflows. Fix
the possible kernel memory leak by zeroing the trailing bytes.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_msgtype6.c | 77 +++++++++++++--------------
1 file changed, 37 insertions(+), 40 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index 40f72cdf284d..2e4aef330b68 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -342,49 +342,40 @@ static int xcrb_msg_to_type6cprb_msgx(bool userspace, struct ap_message *ap_msg,
};
} __packed * msg = ap_msg->msg;
- int rcblen = CEIL4(xcrb->request_control_blk_length);
- int req_sumlen, resp_sumlen;
- char *req_data = ap_msg->msg + sizeof(struct type6_hdr) + rcblen;
- char *function_code;
+ size_t req_cblen, rep_cblen, req_sumlen, rep_sumlen;
+ char *function_code, *req_data;
- if (CEIL4(xcrb->request_control_blk_length) <
- xcrb->request_control_blk_length)
- return -EINVAL; /* overflow after alignment*/
-
- /* length checks */
+ /* request length and overflow checks */
+ if (xcrb->request_control_blk_length < sizeof(struct CPRBX))
+ return -EINVAL;
+ req_cblen = CEIL4((size_t)xcrb->request_control_blk_length);
+ if (req_cblen > U32_MAX)
+ return -EINVAL;
ap_msg->len = sizeof(struct type6_hdr) +
- CEIL4(xcrb->request_control_blk_length) +
- xcrb->request_data_length;
+ req_cblen + xcrb->request_data_length;
if (ap_msg->len > ap_msg->bufsize)
return -EINVAL;
-
- /*
- * Overflow check
- * sum must be greater (or equal) than the largest operand
- */
- req_sumlen = CEIL4(xcrb->request_control_blk_length) +
- xcrb->request_data_length;
- if ((CEIL4(xcrb->request_control_blk_length) <=
- xcrb->request_data_length) ?
+ req_sumlen = req_cblen + xcrb->request_data_length;
+ if (req_sumlen > U32_MAX)
+ return -EINVAL;
+ if (req_cblen <= xcrb->request_data_length ?
req_sumlen < xcrb->request_data_length :
- req_sumlen < CEIL4(xcrb->request_control_blk_length)) {
+ req_sumlen < req_cblen) {
return -EINVAL;
}
- if (CEIL4(xcrb->reply_control_blk_length) <
- xcrb->reply_control_blk_length)
- return -EINVAL; /* overflow after alignment*/
-
- /*
- * Overflow check
- * sum must be greater (or equal) than the largest operand
- */
- resp_sumlen = CEIL4(xcrb->reply_control_blk_length) +
- xcrb->reply_data_length;
- if ((CEIL4(xcrb->reply_control_blk_length) <=
- xcrb->reply_data_length) ?
- resp_sumlen < xcrb->reply_data_length :
- resp_sumlen < CEIL4(xcrb->reply_control_blk_length)) {
+ /* reply length and overflow checks */
+ if (xcrb->reply_control_blk_length < sizeof(struct CPRBX))
+ return -EINVAL;
+ rep_cblen = CEIL4((size_t)xcrb->reply_control_blk_length);
+ if (rep_cblen > U32_MAX)
+ return -EINVAL;
+ rep_sumlen = rep_cblen + xcrb->reply_data_length;
+ if (rep_sumlen > U32_MAX)
+ return -EINVAL;
+ if (rep_cblen <= xcrb->reply_data_length ?
+ rep_sumlen < xcrb->reply_data_length :
+ rep_sumlen < rep_cblen) {
return -EINVAL;
}
@@ -393,7 +384,7 @@ static int xcrb_msg_to_type6cprb_msgx(bool userspace, struct ap_message *ap_msg,
memcpy(msg->hdr.agent_id, &xcrb->agent_ID, sizeof(xcrb->agent_ID));
msg->hdr.tocardlen1 = xcrb->request_control_blk_length;
if (xcrb->request_data_length) {
- msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
+ msg->hdr.offset2 = msg->hdr.offset1 + req_cblen;
msg->hdr.tocardlen2 = xcrb->request_data_length;
}
msg->hdr.fromcardlen1 = xcrb->reply_control_blk_length;
@@ -404,6 +395,9 @@ static int xcrb_msg_to_type6cprb_msgx(bool userspace, struct ap_message *ap_msg,
xcrb->request_control_blk_addr,
xcrb->request_control_blk_length))
return -EFAULT;
+ if (xcrb->request_control_blk_length < req_cblen)
+ memset(msg->userdata + xcrb->request_control_blk_length,
+ 0, req_cblen - xcrb->request_control_blk_length);
if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
xcrb->request_control_blk_length)
return -EINVAL;
@@ -437,10 +431,13 @@ static int xcrb_msg_to_type6cprb_msgx(bool userspace, struct ap_message *ap_msg,
}
/* copy data block */
- if (xcrb->request_data_length &&
- z_copy_from_user(userspace, req_data, xcrb->request_data_address,
- xcrb->request_data_length))
- return -EFAULT;
+ if (xcrb->request_data_length) {
+ req_data = ap_msg->msg + sizeof(struct type6_hdr) + req_cblen;
+ if (z_copy_from_user(userspace, req_data,
+ xcrb->request_data_address,
+ xcrb->request_data_length))
+ return -EFAULT;
+ }
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 2/2] s390/zcrypt: Improve EP11 CPRB length and overflow checks
2026-07-24 13:45 [PATCH v4 0/2] Improve code in zcrypt msg type 6 handling Harald Freudenberger
2026-07-24 13:45 ` [PATCH v4 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger
@ 2026-07-24 13:45 ` Harald Freudenberger
2026-07-24 14:29 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Harald Freudenberger @ 2026-07-24 13:45 UTC (permalink / raw)
To: dengler, fcallies
Cc: freude, linux-s390, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev
The xcrb_msg_to_type6_ep11cprb_msgx() function lacks proper input
validation, creating security vulnerabilities:
1. Missing minimum size validation: The ep11_cprb structure and
subsequent payload fields (pld_tag, pld_lenfmt) are copied from
userspace without verifying sufficient buffer length.
2. Arithmetic overflow in length calculations: CEIL4 alignment could
overflow, bypassing size checks and enabling buffer overflows.
Fix by using size_t for length calculations, adding U32_MAX boundary
checks after alignment, and validating minimum request size and
minimum reply size before copying from userspace.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_msgtype6.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index 2e4aef330b68..6f49165d7732 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -477,16 +477,24 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(bool userspace, struct ap_message *ap
unsigned int dom_val; /* domain id */
} __packed * payload_hdr = NULL;
- if (CEIL4(xcrb->req_len) < xcrb->req_len)
- return -EINVAL; /* overflow after alignment*/
+ size_t req_len, rep_len;
- /* length checks */
- ap_msg->len = sizeof(struct type6_hdr) + CEIL4(xcrb->req_len);
+ /* request length and overflow checks */
+ if (xcrb->req_len < sizeof(struct ep11_cprb) + 2 * sizeof(unsigned char))
+ return -EINVAL;
+ req_len = CEIL4(xcrb->req_len);
+ if (req_len < xcrb->req_len || req_len > U32_MAX)
+ return -EINVAL;
+ ap_msg->len = sizeof(struct type6_hdr) + req_len;
if (ap_msg->len > ap_msg->bufsize)
return -EINVAL;
- if (CEIL4(xcrb->resp_len) < xcrb->resp_len)
- return -EINVAL; /* overflow after alignment*/
+ /* reply length and overflow checks */
+ if (xcrb->resp_len < sizeof(struct ep11_cprb))
+ return -EINVAL;
+ rep_len = CEIL4(xcrb->resp_len);
+ if (rep_len < xcrb->resp_len || rep_len > U32_MAX)
+ return -EINVAL;
/* prepare type6 header */
msg->hdr = static_type6_ep11_hdr;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks
2026-07-24 13:45 ` [PATCH v4 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger
@ 2026-07-24 14:21 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-07-24 14:21 UTC (permalink / raw)
To: Harald Freudenberger
Cc: linux-s390, Vasily Gorbik, Heiko Carstens, Alexander Gordeev
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] This problem wasn't introduced by this patch, but the patch completely misses identical logic flaws in the EP11 path (`xcrb_msg_to_type6_ep11cprb_msgx`). While the patch successfully fixes critical vulnerabilities in the CCA path, it leaves the kernel vulnerable to a catastrophic kernel panic (DoS), uninitialized kernel memory reads, and an uninitialized memory leak to hardware via the `ZSENDEP11CPRB` ioctl.
--
--- Patch [1]: [PATCH v4 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks ---
commit 0472132f230811c8d94963dccf05ca137d96d8ec
Author: Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: Improve CCA CPRB length and overflow checks
This patch fixes integer overflows, minimum size validation, and potential
kernel memory leaks in xcrb_msg_to_type6cprb_msgx(). It adds U32_MAX
boundary checks, validates minimum control block sizes, and zeros trailing
bytes to prevent leaking uninitialized memory.
> diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
> index 40f72cdf284d3..2e4aef330b680 100644
> --- a/drivers/s390/crypto/zcrypt_msgtype6.c
> +++ b/drivers/s390/crypto/zcrypt_msgtype6.c
> @@ -342,49 +342,40 @@ static int xcrb_msg_to_type6cprb_msgx(bool userspace, struct ap_message *ap_msg,
> };
> } __packed * msg = ap_msg->msg;
>
> - int rcblen = CEIL4(xcrb->request_control_blk_length);
> - int req_sumlen, resp_sumlen;
> - char *req_data = ap_msg->msg + sizeof(struct type6_hdr) + rcblen;
> - char *function_code;
> + size_t req_cblen, rep_cblen, req_sumlen, rep_sumlen;
> + char *function_code, *req_data;
>
> - if (CEIL4(xcrb->request_control_blk_length) <
> - xcrb->request_control_blk_length)
> - return -EINVAL; /* overflow after alignment*/
> -
> - /* length checks */
> + /* request length and overflow checks */
> + if (xcrb->request_control_blk_length < sizeof(struct CPRBX))
> + return -EINVAL;
> + req_cblen = CEIL4((size_t)xcrb->request_control_blk_length);
[Severity: Critical]
This is a pre-existing issue, but does xcrb_msg_to_type6_ep11cprb_msgx()
need these same fixes?
It looks like the EP11 path has the same logic flaws that this patch fixes
for the CCA path. For example, if a large req_len is provided, couldn't the
length calculation wrap around and bypass the buffer size check?
drivers/s390/crypto/zcrypt_msgtype6.c:xcrb_msg_to_type6_ep11cprb_msgx()
...
ap_msg->len = sizeof(struct type6_hdr) + CEIL4(xcrb->req_len);
...
If the buffer size check is bypassed, could z_copy_from_user() fail
access_ok() and zero out the destination buffer with a massive length,
crashing the kernel?
drivers/s390/crypto/zcrypt_msgtype6.c:xcrb_msg_to_type6_ep11cprb_msgx()
...
if (z_copy_from_user(userspace, msg->userdata,
(char __force __user *)xcrb->req, xcrb->req_len)) {
...
Additionally, if req_len is very small, could this lead to uninitialized
memory reads when accessing msg->pld_lenfmt, since there doesn't appear to
be a minimum control block size check?
drivers/s390/crypto/zcrypt_msgtype6.c:xcrb_msg_to_type6_ep11cprb_msgx()
...
if ((msg->pld_lenfmt & 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/
...
Finally, if req_len requires padding, does the trailing padding get zeroed
out, or could it leak uninitialized kernel heap memory to the hardware?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260724134556.144597-1-freude@linux.ibm.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 2/2] s390/zcrypt: Improve EP11 CPRB length and overflow checks
2026-07-24 13:45 ` [PATCH v4 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger
@ 2026-07-24 14:29 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-07-24 14:29 UTC (permalink / raw)
To: Harald Freudenberger
Cc: Vasily Gorbik, Alexander Gordeev, linux-s390, Heiko Carstens
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [Medium] Incomplete minimum length check for EP11 CPRB requests leads to out-of-bounds reads and writes of uninitialized kernel heap memory.
- [Medium] Uninitialized padding bytes are leaked to the AP coprocessor hardware.
--
--- Patch [2]: [PATCH v4 2/2] s390/zcrypt: Improve EP11 CPRB length and overflow checks ---
commit 35795525c75a20e288cf1cb8e4a3621e47212c8d
Author: Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: Improve EP11 CPRB length and overflow checks
The xcrb_msg_to_type6_ep11cprb_msgx() function lacks proper input
validation, creating security vulnerabilities:
1. Missing minimum size validation: The ep11_cprb structure and
subsequent payload fields (pld_tag, pld_lenfmt) are copied from
userspace without verifying sufficient buffer length.
2. Arithmetic overflow in length calculations: CEIL4 alignment could
overflow, bypassing size checks and enabling buffer overflows.
> diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
> index 2e4aef330b680..6f49165d7732e 100644
> --- a/drivers/s390/crypto/zcrypt_msgtype6.c
> +++ b/drivers/s390/crypto/zcrypt_msgtype6.c
> @@ -477,16 +477,24 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(bool userspace, struct ap_message *ap
> unsigned int dom_val; /* domain id */
> } __packed * payload_hdr = NULL;
>
> - if (CEIL4(xcrb->req_len) < xcrb->req_len)
> - return -EINVAL; /* overflow after alignment*/
> + size_t req_len, rep_len;
>
> - /* length checks */
> - ap_msg->len = sizeof(struct type6_hdr) + CEIL4(xcrb->req_len);
> + /* request length and overflow checks */
> + if (xcrb->req_len < sizeof(struct ep11_cprb) + 2 * sizeof(unsigned char))
> + return -EINVAL;
[Severity: Medium]
This is a pre-existing issue, but does this minimum length check ensure
enough data is copied for the payload header?
Later in xcrb_msg_to_type6_ep11cprb_msgx(), payload_hdr->func_val is accessed:
xcrb_msg_to_type6_ep11cprb_msgx() {
...
payload_hdr = (struct pld_hdr *)((&msg->pld_lenfmt) + lfmt);
*fcode = payload_hdr->func_val & 0xFFFF;
...
}
If xcrb->req_len is smaller than the required size for the payload header,
could this result in reading uninitialized kernel heap memory?
Additionally, could this lead to an out-of-bounds write in
zcrypt_msgtype6_send_ep11_cprb() when it assigns payload_hdr->dom_val?
> + req_len = CEIL4(xcrb->req_len);
> + if (req_len < xcrb->req_len || req_len > U32_MAX)
> + return -EINVAL;
> + ap_msg->len = sizeof(struct type6_hdr) + req_len;
[Severity: Medium]
This isn't a bug introduced by this patch, but do we need to zero out the
padding bytes added by CEIL4()?
If xcrb->req_len is not a multiple of 4, the length is rounded up, but the
padding bytes don't appear to be initialized. Could this leak up to 3 bytes
of uninitialized kernel memory to the AP hardware?
> if (ap_msg->len > ap_msg->bufsize)
> return -EINVAL;
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260724134556.144597-1-freude@linux.ibm.com?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-24 14:29 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-24 13:45 [PATCH v4 0/2] Improve code in zcrypt msg type 6 handling Harald Freudenberger
2026-07-24 13:45 ` [PATCH v4 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger
2026-07-24 14:21 ` sashiko-bot
2026-07-24 13:45 ` [PATCH v4 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger
2026-07-24 14:29 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox