* [PATCH v3 0/2] Improve code in zcrypt msg type 6 handling
@ 2026-07-24 9:51 Harald Freudenberger
2026-07-24 9:51 ` [PATCH v3 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger
2026-07-24 9:51 ` [PATCH v3 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger
0 siblings, 2 replies; 5+ messages in thread
From: Harald Freudenberger @ 2026-07-24 9:51 UTC (permalink / raw)
To: dengler, fcallies
Cc: freude, linux-s390, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev
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
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 | 94 ++++++++++++++-------------
1 file changed, 48 insertions(+), 46 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v3 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks 2026-07-24 9:51 [PATCH v3 0/2] Improve code in zcrypt msg type 6 handling Harald Freudenberger @ 2026-07-24 9:51 ` Harald Freudenberger 2026-07-24 10:33 ` sashiko-bot 2026-07-24 9:51 ` [PATCH v3 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger 1 sibling, 1 reply; 5+ messages in thread From: Harald Freudenberger @ 2026-07-24 9:51 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. 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. Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> --- drivers/s390/crypto/zcrypt_msgtype6.c | 74 ++++++++++++--------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index 40f72cdf284d..4ac767661cb5 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; @@ -437,10 +428,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 v3 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks 2026-07-24 9:51 ` [PATCH v3 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger @ 2026-07-24 10:33 ` sashiko-bot 0 siblings, 0 replies; 5+ messages in thread From: sashiko-bot @ 2026-07-24 10:33 UTC (permalink / raw) To: Harald Freudenberger Cc: linux-s390, Alexander Gordeev, Vasily Gorbik, Heiko Carstens Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] Missing minimum size validation in `xcrb_msg_to_type6_ep11cprb_msgx` allows uninitialized memory access. - [Medium] Uninitialized padding bytes from the kernel heap are leaked to the crypto device hardware. -- --- Patch [1]: [PATCH v3 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks --- commit 67b21feb8736dd104c27309742d4f5d3ebdf4ba8 Author: Harald Freudenberger <freude@linux.ibm.com> s390/zcrypt: Improve CCA CPRB length and overflow checks This commit improves CCA CPRB length and overflow checks in xcrb_msg_to_type6cprb_msgx(). It switches to using size_t for length calculations and adds U32_MAX boundary checks after alignment. It also introduces minimum control block size validation before copying data from userspace. > diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c > index 40f72cdf284d3..4ac767661cb50 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; [Severity: Medium] This is a pre-existing issue, but does this code leak uninitialized memory to the hardware? Because ap_msg->len incorporates the 4-byte aligned req_cblen, but the subsequent z_copy_from_user() only copies xcrb->request_control_blk_length bytes, the trailing padding bytes in ap_msg->msg could remain uninitialized. When this message is sent over the bus, does this leak kernel heap data to the crypto device hardware? > if (ap_msg->len > ap_msg->bufsize) > return -EINVAL; [ ... ] > @@ -437,10 +428,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; > } [Severity: High] This isn't a bug introduced by this patch, but while you are fixing the length checks in xcrb_msg_to_type6cprb_msgx(), does xcrb_msg_to_type6_ep11cprb_msgx() need similar minimum size validation? In xcrb_msg_to_type6_ep11cprb_msgx(), there does not appear to be a check for a minimum size before reading xcrb->req_len bytes: /* 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; } if ((msg->pld_lenfmt & 0x80) == 0x80) { If an unprivileged user space application issues a ZSENDEP11CPRB ioctl with req_len smaller than the required control block size, could this result in subsequent code parsing uninitialized trailing bytes from msg->userdata? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260724095128.140810-1-freude@linux.ibm.com?part=1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 2/2] s390/zcrypt: Improve EP11 CPRB length and overflow checks 2026-07-24 9:51 [PATCH v3 0/2] Improve code in zcrypt msg type 6 handling Harald Freudenberger 2026-07-24 9:51 ` [PATCH v3 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger @ 2026-07-24 9:51 ` Harald Freudenberger 2026-07-24 10:32 ` sashiko-bot 1 sibling, 1 reply; 5+ messages in thread From: Harald Freudenberger @ 2026-07-24 9:51 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. 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 ep11_cprb structure and subsequent payload fields (pld_tag, pld_lenfmt) are copied from userspace without verifying sufficient buffer length. 3. 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 4ac767661cb5..3b56b7745588 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -474,16 +474,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 > 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 > 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 v3 2/2] s390/zcrypt: Improve EP11 CPRB length and overflow checks 2026-07-24 9:51 ` [PATCH v3 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger @ 2026-07-24 10:32 ` sashiko-bot 0 siblings, 0 replies; 5+ messages in thread From: sashiko-bot @ 2026-07-24 10:32 UTC (permalink / raw) To: Harald Freudenberger Cc: Heiko Carstens, Vasily Gorbik, linux-s390, Alexander Gordeev Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] The patch replaces a working 64-bit integer overflow check with a flawed one, introducing a bypass for 64-bit wrap-arounds in the CEIL4 macro that allows a Denial of Service (DoS) via usercopy hardening. -- --- Patch [2]: [PATCH v3 2/2] s390/zcrypt: Improve EP11 CPRB length and overflow checks --- commit b608e764c33b544400d55b5be70e199d907fd586 Author: Harald Freudenberger <freude@linux.ibm.com> s390/zcrypt: Improve EP11 CPRB length and overflow checks This commit modifies length and overflow checks for EP11 CPRB requests and replies. It replaces an existing overflow check with a U32_MAX check after alignment and adds minimum size validations before copying from userspace. > diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c > index 4ac767661cb50..3b56b7745588c 100644 > --- a/drivers/s390/crypto/zcrypt_msgtype6.c > +++ b/drivers/s390/crypto/zcrypt_msgtype6.c > @@ -474,16 +474,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 > U32_MAX) > + return -EINVAL; [Severity: High] Does this new check fail to detect 64-bit wrap-arounds that the old check correctly caught? If xcrb->req_len is set to U64_MAX - 1 (0xFFFFFFFFFFFFFFFE), the + 3 inside the CEIL4 macro wraps around in 64-bit unsigned arithmetic to 1, causing CEIL4 to evaluate to 0. Since req_len becomes 0, the req_len > U32_MAX check passes, bypassing the length validation. Later in xcrb_msg_to_type6_ep11cprb_msgx(), z_copy_from_user() is called with this massive, unvalidated xcrb->req_len: if (z_copy_from_user(userspace, msg->userdata, (char __force __user *)xcrb->req, xcrb->req_len)) { Could this large size passed to z_copy_from_user() trigger a WARN_ON_ONCE in the kernel's usercopy hardening (check_copy_size) because bytes > INT_MAX, potentially leading to a kernel panic in environments with panic_on_warn enabled? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260724095128.140810-1-freude@linux.ibm.com?part=2 ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-24 10:33 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-24 9:51 [PATCH v3 0/2] Improve code in zcrypt msg type 6 handling Harald Freudenberger 2026-07-24 9:51 ` [PATCH v3 1/2] s390/zcrypt: Improve CCA CPRB length and overflow checks Harald Freudenberger 2026-07-24 10:33 ` sashiko-bot 2026-07-24 9:51 ` [PATCH v3 2/2] s390/zcrypt: Improve EP11 " Harald Freudenberger 2026-07-24 10:32 ` sashiko-bot
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.