* [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
* 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
* [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 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