From: sashiko-bot@kernel.org
To: "Dave Jiang" <dave.jiang@intel.com>
Cc: linux-cxl@vger.kernel.org
Subject: Re: [PATCH] cxl/test: Verify cmd->size_in before accessing payload
Date: Fri, 05 Jun 2026 17:29:47 +0000 [thread overview]
Message-ID: <20260605172948.4883A1F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260605171107.3855381-1-dave.jiang@intel.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Integer overflow in payload bounds checking allows massive out-of-bounds memory reads and writes in `mock_get_log`, `mock_get_lsa`, and `mock_set_lsa`.
- [Critical] Feature handlers blindly write to `cmd->payload_out` based on parameters derived from the input payload without verifying that the destination buffer is sufficiently sized.
- [High] The `cmd->size_in == 0` checks added in `mock_clear_event` and `mock_get_test_feature` are insufficient to prevent out-of-bounds reads for payloads smaller than the expected structure size.
- [High] The patch misses several mailbox handlers that dereference `cmd->payload_in` without checking its size, and the fix in `mock_get_test_feature` is completely bypassed by its caller.
- [High] `cxl_mock_mbox_send` does not serialize concurrent mailbox commands, leading to widespread race conditions across the mock device state.
--
commit 26d56860aa1c2848111addf4d017916d442515a1
Author: Dave Jiang <dave.jiang@intel.com>
cxl/test: Verify cmd->size_in before accessing payload
Adds a check for cmd->size_in before accessing the payload. This prevents
potential dereferencing of a null pointer if size_in is zero.
Link: https://lore.kernel.org/linux-cxl/20260605143748.235271F00893@smtp.kernel.org/
> diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
> index 271c7ad8cc32c..5d812b10fbc87 100644
> --- a/tools/testing/cxl/test/mem.c
> +++ b/tools/testing/cxl/test/mem.c
> @@ -312,12 +312,17 @@ static int mock_clear_event(struct device *dev, struct cxl_mbox_cmd *cmd)
> {
> - struct cxl_mbox_clear_event_payload *pl = cmd->payload_in;
> + struct cxl_mbox_clear_event_payload *pl;
> struct mock_event_log *log;
> - u8 log_type = pl->event_log;
> + u8 log_type;
> u16 handle;
> int nr;
>
> + if (cmd->size_in == 0)
> + return -EINVAL;
> +
[Severity: High]
This is a pre-existing issue, but is the size_in == 0 check sufficient?
If userspace provides a payload with cmd->size_in == 1, the check passes.
The handler then casts the truncated buffer to struct
cxl_mbox_clear_event_payload and reads subsequent fields out-of-bounds.
Should this check verify that cmd->size_in >= sizeof(*pl)?
> + pl = cmd->payload_in;
> + log_type = pl->event_log;
[ ... ]
> @@ -574,14 +579,19 @@ static int mock_get_log(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *cmd)
> {
> struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
> - struct cxl_mbox_get_log *gl = cmd->payload_in;
> - u32 offset = le32_to_cpu(gl->offset);
> - u32 length = le32_to_cpu(gl->length);
> uuid_t uuid = DEFINE_CXL_CEL_UUID;
> + struct cxl_mbox_get_log *gl;
> void *data = &mock_cel;
> + u32 offset;
> + u32 length;
>
> if (cmd->size_in < sizeof(*gl))
> return -EINVAL;
> +
> + gl = cmd->payload_in;
> + offset = le32_to_cpu(gl->offset);
> + length = le32_to_cpu(gl->length);
> +
> if (length > cxl_mbox->payload_size)
> return -EINVAL;
> if (offset + length > sizeof(mock_cel))
[Severity: Critical]
This isn't a bug introduced by this patch, but does the offset + length
computation overflow 32-bit boundaries here?
Because offset and length are 32-bit unsigned integers derived from user
payloads, a very large offset and a small length could overflow their sum
to a small positive value, passing the size check. The subsequent memcpy
would then allow a massive out-of-bounds read or write up to 4GB away.
Similar integer overflows appear to exist in mock_get_lsa() and
mock_set_lsa().
> return -EINVAL;
[ ... ]
> @@ -1415,11 +1429,18 @@ static int mock_get_test_feature(struct cxl_mockmem_data *mdata,
> struct cxl_mbox_cmd *cmd)
> {
> struct vendor_test_feat *output = cmd->payload_out;
> - struct cxl_mbox_get_feat_in *input = cmd->payload_in;
> - u16 offset = le16_to_cpu(input->offset);
> - u16 count = le16_to_cpu(input->count);
> + struct cxl_mbox_get_feat_in *input;
> + u16 offset;
> + u16 count;
> u8 *ptr;
>
> + if (cmd->size_in == 0)
> + return -EINVAL;
> +
[Severity: High]
This is a pre-existing issue, but does checking cmd->size_in == 0 fully
prevent out-of-bounds reads?
If the payload is smaller than struct cxl_mbox_get_feat_in, the check
passes but the cast causes an out-of-bounds read when accessing fields
like input->count.
Also, the caller mock_get_feature() seems to unconditionally evaluate
uuid_equal(&input->uuid, ...) prior to calling mock_get_test_feature():
tools/testing/cxl/test/mem.c:mock_get_feature() {
struct cxl_mbox_get_feat_in *input = cmd->payload_in;
if (uuid_equal(&input->uuid, &CXL_VENDOR_FEATURE_TEST))
...
}
Because input is cmd->payload_in, this leads to a ZERO_SIZE_PTR
dereference before the newly added size_in == 0 check is reached.
Other mailbox handlers like mock_activate_fw() also appear to lack size_in
verification.
> + input = cmd->payload_in;
> + offset = le16_to_cpu(input->offset);
> + count = le16_to_cpu(input->count);
> +
> if (offset > sizeof(*output)) {
> cmd->return_code = CXL_MBOX_CMD_RC_INPUT;
> return -EINVAL;
> }
>
> if (offset + count > sizeof(*output)) {
> cmd->return_code = CXL_MBOX_CMD_RC_INPUT;
> return -EINVAL;
> }
>
> ptr = (u8 *)&mdata->test_feat + offset;
> memcpy((u8 *)output + offset, ptr, count);
[Severity: Critical]
This isn't a bug introduced by this patch, but does this code perform a
memcpy into cmd->payload_out without validating that
offset + count <= cmd->size_out?
If a user provides an undersized size_out but requests a larger read via
input->count, the memcpy will write past the end of the dynamically
allocated buffer. The same pattern seems to exist in
mock_get_supported_features() when writing to out->ents.
>
> return 0;
> }
[Severity: High]
This is a pre-existing issue, but does cxl_mock_mbox_send() fail to
serialize concurrent mailbox commands?
Looking at cxl_mock_mbox_send():
tools/testing/cxl/test/mem.c:cxl_mock_mbox_send() {
struct device *dev = cxl_mbox->host;
...
}
It dispatches mailbox commands without acquiring cxl_mbox->mbox_mutex,
which violates the subsystem's synchronization model. Concurrent IOCTLs
from userspace can execute mock handlers simultaneously, causing data
races and corruptions on shared mock structures.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605171107.3855381-1-dave.jiang@intel.com?part=1
prev parent reply other threads:[~2026-06-05 17:29 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-05 17:11 [PATCH] cxl/test: Verify cmd->size_in before accessing payload Dave Jiang
2026-06-05 17:29 ` sashiko-bot [this message]
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=20260605172948.4883A1F00893@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dave.jiang@intel.com \
--cc=linux-cxl@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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