* [PATCH v5 0/2] Improve code in zcrypt msg type 6 handling
@ 2026-07-24 15:16 Harald Freudenberger
2026-07-24 15:16 ` [PATCH v5 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger
2026-07-24 15:16 ` [PATCH v5 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger
0 siblings, 2 replies; 5+ messages in thread
From: Harald Freudenberger @ 2026-07-24 15:16 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.
v5: - Yea, sashiko still found out that the min req size needs
to take the minimal payload header into account. Fixed.
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 | 98 ++++++++++++++-------------
1 file changed, 52 insertions(+), 46 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v5 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks
2026-07-24 15:16 [PATCH v5 0/2] Improve code in zcrypt msg type 6 handling Harald Freudenberger
@ 2026-07-24 15:16 ` Harald Freudenberger
2026-07-24 15:39 ` sashiko-bot
2026-07-24 15:16 ` [PATCH v5 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger
1 sibling, 1 reply; 5+ messages in thread
From: Harald Freudenberger @ 2026-07-24 15:16 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 v5 2/2] s390/zcrypt: Improve EP11 CPRB length and overflow checks
2026-07-24 15:16 [PATCH v5 0/2] Improve code in zcrypt msg type 6 handling Harald Freudenberger
2026-07-24 15:16 ` [PATCH v5 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger
@ 2026-07-24 15:16 ` Harald Freudenberger
2026-07-24 15:57 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Harald Freudenberger @ 2026-07-24 15:16 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 | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index 2e4aef330b68..f7a504f5d54e 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -477,16 +477,25 @@ 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) + sizeof(struct pld_hdr))
+ 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 v5 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks
2026-07-24 15:16 ` [PATCH v5 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger
@ 2026-07-24 15:39 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-07-24 15:39 UTC (permalink / raw)
To: Harald Freudenberger
Cc: Alexander Gordeev, Heiko Carstens, linux-s390, Vasily Gorbik
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Integer overflow in EP11 length calculation bypasses bounds check, leading to DoS.
- [High] Missing minimum size validation and uninitialized padding memory leak in EP11 message processing.
--
--- Patch [1]: [PATCH v5 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks ---
commit db060c7765ef46ae0c3f096c8f02b7e395cb8a36
Author: Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: Improve CCA CPRB length and overflow checks
This commit fixes several security vulnerabilities in the CCA CPRB message
processing function by adding minimum size validation, fixing integer
overflows during alignment, and preventing memory leaks by zeroing trailing
bytes.
> 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;
[Severity: High]
This isn't a bug introduced by this patch, but does the same missing size
validation issue exist in the EP11 counterpart
xcrb_msg_to_type6_ep11cprb_msgx() in the same file?
In xcrb_msg_to_type6_ep11cprb_msgx():
ap_msg->len = sizeof(struct type6_hdr) + CEIL4(xcrb->req_len);
Without a minimum size check on xcrb->req_len (e.g., against
sizeof(struct ep11_cprb)), could this parse uninitialized kernel memory from
ap_init_apmsg() if userspace passes a very small length via the
ZSENDEP11CPRB ioctl?
Later in the same function:
if (msg->cprbx.flags & 0x80)
ap_msg->flags |= AP_MSG_FLAG_ADMIN;
Could this uninitialized memory dictate administration privileges, or leak
uninitialized padding to the hardware?
> + 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;
[Severity: Critical]
This is a pre-existing issue, but could the lack of an overflow check in
xcrb_msg_to_type6_ep11cprb_msgx() lead to a denial of service?
In xcrb_msg_to_type6_ep11cprb_msgx(), the length calculation lacks similar
boundary checks:
ap_msg->len = sizeof(struct type6_hdr) + CEIL4(xcrb->req_len);
if (ap_msg->len > ap_msg->bufsize)
return -EINVAL;
If a local user supplies a massive value for xcrb->req_len
(e.g., 0xFFFFFFFFFFFFFFF0), could CEIL4() wrap around a 64-bit boundary,
resulting in a small length that bypasses the bufsize check?
If bypassed, it would reach the copy operation:
if (z_copy_from_user(userspace, msg->userdata,
(char __force __user *)xcrb->req, xcrb->req_len)) {
When copy_from_user() fails its access_ok check with this massive length,
would it execute memset(..., 0, 0xFFFFFFFFFFFFFFF0), causing an
out-of-bounds write that immediately panics the kernel?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260724151616.147765-1-freude@linux.ibm.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5 2/2] s390/zcrypt: Improve EP11 CPRB length and overflow checks
2026-07-24 15:16 ` [PATCH v5 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger
@ 2026-07-24 15:57 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-07-24 15:57 UTC (permalink / raw)
To: Harald Freudenberger
Cc: Alexander Gordeev, linux-s390, Heiko Carstens, Vasily Gorbik
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Padding bytes introduced by CEIL4 alignment are not zero-initialized, causing up to 3 bytes of uninitialized kernel heap memory to be leaked to the crypto hardware over the AP bus. This problem wasn't introduced by this patch, but it remains a security vulnerability.
--
--- Patch [2]: [PATCH v5 2/2] s390/zcrypt: Improve EP11 CPRB length and overflow checks ---
commit c3d8ef25f1e2612bc37abf0a2ac52df48c88d9ee
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. This patch fixes these 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.
> diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
> index 2e4aef330b680..f7a504f5d54e3 100644
> --- a/drivers/s390/crypto/zcrypt_msgtype6.c
> +++ b/drivers/s390/crypto/zcrypt_msgtype6.c
> @@ -477,16 +477,25 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(bool userspace, struct ap_message *ap
[ ... ]
> + 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;
[Severity: High]
This is a pre-existing issue, but does this code leave up to 3 bytes of
uninitialized kernel memory in the message buffer when xcrb->req_len is not
4-byte aligned?
When copying the request data from userspace just below this code in
xcrb_msg_to_type6_ep11cprb_msgx():
/* Import CPRB data from the ioctl input parameter */
if (z_copy_from_user(userspace, msg->userdata,
(char __force __user *)xcrb->req, xcrb->req_len)) {
return -EFAULT;
}
The copy only transfers xcrb->req_len bytes. Because the message length
dispatched to the hardware includes the padding bytes up to CEIL4(xcrb->req_len),
uninitialized memory could be leaked.
Should there be a memset to zero-initialize the remaining padding bytes before
the message is dispatched?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260724151616.147765-1-freude@linux.ibm.com?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-24 15:57 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-24 15:16 [PATCH v5 0/2] Improve code in zcrypt msg type 6 handling Harald Freudenberger
2026-07-24 15:16 ` [PATCH v5 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger
2026-07-24 15:39 ` sashiko-bot
2026-07-24 15:16 ` [PATCH v5 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger
2026-07-24 15:57 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox