* [PATCH v4 0/6] cxl: Sashiko bug fixes
@ 2026-08-12 11:21 Richard Cheng
2026-08-12 11:21 ` [PATCH v4 1/6] cxl/features: Reject feature offset that overflows 16-bit field Richard Cheng
` (5 more replies)
0 siblings, 6 replies; 10+ messages in thread
From: Richard Cheng @ 2026-08-12 11:21 UTC (permalink / raw)
To: dave, jic23, dave.jiang, alison.schofield, vishal.l.verma
Cc: iweiny, ming.li, gourry, rrichter, linux-cxl, linux-kernel, kees,
newtonl, kristinc, kaihengf, kobak, Richard Cheng
Six independent, pre-existing bugs in the CXL core, reported by
sashiko.
Patch 1: Get/Set Feature derive each mailbox command's offset from the
starting offset plus the amount of data already transferred, then store
it in a 16-bit field. A large offset/count supplied through fwctl can
cause a later offset to exceed the representable feature extent and be
truncated by cpu_to_le16(), targeting the wrong feature data. Reject
invalid ranges up front.
Change cxl_get_feature() to return ssize_t so invalid input and mailbox
failures are reported as negative errno instead of being conflated with
a zero-byte result. Update all EDAC callers for the signed return
contract while preserving the existing fwctl RPC response behavior.
Patch 2: cxl_get_poison_unmapped() aborted its whole partition sweep on
the first fully-mapped partition, silently skipping unmapped poison in
all later partitions. Skip that partition instead.
Patch 3: the same function tolerated the -EFAULT a RAM partition returns
for Get Poison List but left it in rc, so a benign fault on the last
scanned partition surfaced as a spurious read failure. Clear rc, as
poison_by_decoder() already does.
Patch 4: the same function also ignored the ctx->offset handoff from
poison_by_decoder() and derived its scan start from the highest DPA
allocation, so the DPA of allocated-but-uncommitted decoders was never
scanned by either phase. Resume the sweep at ctx->offset.
Patch 5: cxl_get_poison_by_memdev() overwrote rc on each partition
query, so an earlier partition's failure was masked by a later success
and unscanned poison was reported as a clean list. Stop on any error
not tolerated as a RAM -EFAULT.
Patch 6: poison_by_decoder() assumed every decoder with a DPA reservation
was assigned to a partition. Malformed device DPA metadata can leave
dpa_res set while part remains -1, causing a poison scan to access
before the partition array. Reject such decoders before the lookup.
Changes since v3 [1]:
- Patch 1~5: Rebase onto cxl/next
- Patch 6: New patch
[1]:
https://lore.kernel.org/linux-cxl/20260708074228.43654-1-icheng@nvidia.com/
Richard Cheng (6):
cxl/features: Reject feature offset that overflows 16-bit field
cxl/region: Scan all partitions for unmapped poison
cxl/region: Don't leak tolerated RAM -EFAULT from unmapped poison scan
cxl/region: Start unmapped poison scan at the committed decoder
boundary
cxl/memdev: Don't overwrite the error from an earlier partition poison
query
cxl/region: Reject poison scan for decoder without a partition
drivers/cxl/core/core.h | 8 ++++----
drivers/cxl/core/edac.c | 20 +++++++++++++++-----
drivers/cxl/core/features.c | 28 ++++++++++++++++++----------
drivers/cxl/core/memdev.c | 2 ++
drivers/cxl/core/region.c | 15 ++++++++-------
5 files changed, 47 insertions(+), 26 deletions(-)
base-commit: 7098e9cd98a05c0c5de2fae0c2465f9d966fdd07
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4 1/6] cxl/features: Reject feature offset that overflows 16-bit field
2026-08-12 11:21 [PATCH v4 0/6] cxl: Sashiko bug fixes Richard Cheng
@ 2026-08-12 11:21 ` Richard Cheng
2026-08-12 11:52 ` sashiko-bot
2026-08-12 11:21 ` [PATCH v4 2/6] cxl/region: Scan all partitions for unmapped poison Richard Cheng
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Richard Cheng @ 2026-08-12 11:21 UTC (permalink / raw)
To: dave, jic23, dave.jiang, alison.schofield, vishal.l.verma
Cc: iweiny, ming.li, gourry, rrichter, linux-cxl, linux-kernel, kees,
newtonl, kristinc, kaihengf, kobak, Richard Cheng
cxl_get_feature() and cxl_set_feature() build each mailbox command's
offset from the starting offset plus the amount of data already
transferred, then store it in a 16-bit field. A user-controlled fwctl
offset and transfer size can exceed the feature extent, allowing a later
offset to be truncated by cpu_to_le16() and target the wrong feature
data.
Reject requests whose transfer size exceeds the remaining 16-bit feature
range. Express the check as "size > U16_MAX - offset" so the validation
itself cannot wrap on 32-bit systems.
Change cxl_get_feature() to return ssize_t so invalid input and mailbox
failures are reported as negative errno rather than being conflated with
a zero-byte result. Update the EDAC callers to handle negative results.
Keep fwctl behavior unchanged by translating helper failures to the same
header-only RPC response carrying the CXL mailbox return code.
Fixes: 5e5ac21f629d ("cxl/mbox: Add GET_FEATURE mailbox command")
Fixes: 14d502cc2718 ("cxl/mbox: Add SET_FEATURE mailbox command")
Signed-off-by: Richard Cheng <icheng@nvidia.com>
---
drivers/cxl/core/core.h | 8 ++++----
drivers/cxl/core/edac.c | 20 +++++++++++++++-----
drivers/cxl/core/features.c | 28 ++++++++++++++++++----------
3 files changed, 37 insertions(+), 19 deletions(-)
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 35eaf636adc9..bb380ec6daeb 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -217,10 +217,10 @@ int cxl_port_get_possible_dports(struct cxl_port *port);
#ifdef CONFIG_CXL_FEATURES
struct cxl_feat_entry *
cxl_feature_info(struct cxl_features_state *cxlfs, const uuid_t *uuid);
-size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
- enum cxl_get_feat_selection selection,
- void *feat_out, size_t feat_out_size, u16 offset,
- u16 *return_code);
+ssize_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
+ enum cxl_get_feat_selection selection,
+ void *feat_out, size_t feat_out_size, u16 offset,
+ u16 *return_code);
int cxl_set_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
u8 feat_version, const void *feat_data,
size_t feat_data_size, u32 feat_flag, u16 offset,
diff --git a/drivers/cxl/core/edac.c b/drivers/cxl/core/edac.c
index b321971fef58..f1df4b5cfe5b 100644
--- a/drivers/cxl/core/edac.c
+++ b/drivers/cxl/core/edac.c
@@ -78,7 +78,7 @@ static int cxl_mem_scrub_get_attrbs(struct cxl_mailbox *cxl_mbox, u8 *cap,
u16 *cycle, u8 *flags, u8 *min_cycle)
{
size_t rd_data_size = sizeof(struct cxl_scrub_rd_attrbs);
- size_t data_size;
+ ssize_t data_size;
struct cxl_scrub_rd_attrbs *rd_attrbs __free(kfree) =
kzalloc(rd_data_size, GFP_KERNEL);
if (!rd_attrbs)
@@ -87,6 +87,8 @@ static int cxl_mem_scrub_get_attrbs(struct cxl_mailbox *cxl_mbox, u8 *cap,
data_size = cxl_get_feature(cxl_mbox, &CXL_FEAT_PATROL_SCRUB_UUID,
CXL_GET_FEAT_SEL_CURRENT_VALUE, rd_attrbs,
rd_data_size, 0, NULL);
+ if (data_size < 0)
+ return data_size;
if (!data_size)
return -EIO;
@@ -551,7 +553,7 @@ static int cxl_mem_ecs_get_attrbs(struct device *dev,
struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
struct cxl_ecs_fru_rd_attrbs *fru_rd_attrbs;
size_t rd_data_size;
- size_t data_size;
+ ssize_t data_size;
rd_data_size = cxl_ecs_ctx->get_feat_size;
@@ -563,6 +565,8 @@ static int cxl_mem_ecs_get_attrbs(struct device *dev,
data_size = cxl_get_feature(cxl_mbox, &CXL_FEAT_ECS_UUID,
CXL_GET_FEAT_SEL_CURRENT_VALUE, rd_attrbs,
rd_data_size, 0, NULL);
+ if (data_size < 0)
+ return data_size;
if (!data_size)
return -EIO;
@@ -583,7 +587,7 @@ static int cxl_mem_ecs_set_attrbs(struct device *dev,
struct cxl_ecs_fru_wr_attrbs *fru_wr_attrbs;
size_t rd_data_size, wr_data_size;
u16 num_media_frus, count;
- size_t data_size;
+ ssize_t data_size;
num_media_frus = cxl_ecs_ctx->num_media_frus;
rd_data_size = cxl_ecs_ctx->get_feat_size;
@@ -596,6 +600,8 @@ static int cxl_mem_ecs_set_attrbs(struct device *dev,
data_size = cxl_get_feature(cxl_mbox, &CXL_FEAT_ECS_UUID,
CXL_GET_FEAT_SEL_CURRENT_VALUE, rd_attrbs,
rd_data_size, 0, NULL);
+ if (data_size < 0)
+ return data_size;
if (!data_size)
return -EIO;
@@ -1264,7 +1270,7 @@ cxl_mem_sparing_get_attrbs(struct cxl_mem_sparing_context *cxl_sparing_ctx)
struct cxl_memdev *cxlmd = cxl_sparing_ctx->cxlmd;
struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
u16 restriction_flags;
- size_t data_size;
+ ssize_t data_size;
u16 return_code;
struct cxl_memdev_sparing_rd_attrbs *rd_attrbs __free(kfree) =
kzalloc(rd_data_size, GFP_KERNEL);
@@ -1274,6 +1280,8 @@ cxl_mem_sparing_get_attrbs(struct cxl_mem_sparing_context *cxl_sparing_ctx)
data_size = cxl_get_feature(cxl_mbox, &cxl_sparing_ctx->repair_uuid,
CXL_GET_FEAT_SEL_CURRENT_VALUE, rd_attrbs,
rd_data_size, 0, &return_code);
+ if (data_size < 0)
+ return data_size;
if (!data_size)
return -EIO;
@@ -1750,7 +1758,7 @@ static int cxl_mem_ppr_get_attrbs(struct cxl_ppr_context *cxl_ppr_ctx)
struct cxl_memdev *cxlmd = cxl_ppr_ctx->cxlmd;
struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
u16 restriction_flags;
- size_t data_size;
+ ssize_t data_size;
u16 return_code;
struct cxl_memdev_ppr_rd_attrbs *rd_attrbs __free(kfree) =
@@ -1761,6 +1769,8 @@ static int cxl_mem_ppr_get_attrbs(struct cxl_ppr_context *cxl_ppr_ctx)
data_size = cxl_get_feature(cxl_mbox, &cxl_ppr_ctx->repair_uuid,
CXL_GET_FEAT_SEL_CURRENT_VALUE, rd_attrbs,
rd_data_size, 0, &return_code);
+ if (data_size < 0)
+ return data_size;
if (!data_size)
return -EIO;
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
index ba6d2a5acb74..8d44ce829497 100644
--- a/drivers/cxl/core/features.c
+++ b/drivers/cxl/core/features.c
@@ -220,10 +220,10 @@ int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_features, "CXL");
-size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
- enum cxl_get_feat_selection selection,
- void *feat_out, size_t feat_out_size, u16 offset,
- u16 *return_code)
+ssize_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
+ enum cxl_get_feat_selection selection,
+ void *feat_out, size_t feat_out_size, u16 offset,
+ u16 *return_code)
{
size_t data_to_rd_size;
struct cxl_mbox_get_feat_in pi;
@@ -235,7 +235,10 @@ size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
*return_code = CXL_MBOX_CMD_RC_INPUT;
if (!feat_out || !feat_out_size)
- return 0;
+ return -EINVAL;
+
+ if (feat_out_size > U16_MAX - offset)
+ return -EINVAL;
uuid_copy(&pi.uuid, feat_uuid);
pi.selection = selection;
@@ -259,7 +262,7 @@ size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
if (rc < 0 || !mbox_cmd.size_out) {
if (return_code)
*return_code = mbox_cmd.return_code;
- return 0;
+ return rc < 0 ? rc : -EIO;
}
data_rcvd_size += mbox_cmd.size_out;
} while (data_rcvd_size < feat_out_size);
@@ -288,6 +291,9 @@ int cxl_set_feature(struct cxl_mailbox *cxl_mbox,
if (return_code)
*return_code = CXL_MBOX_CMD_RC_INPUT;
+ if (feat_data_size > U16_MAX - offset)
+ return -EINVAL;
+
struct cxl_mbox_set_feat_in *pi __free(kfree) =
kzalloc(cxl_mbox->payload_size, GFP_KERNEL);
if (!pi)
@@ -462,6 +468,7 @@ static void *cxlctl_get_feature(struct cxl_features_state *cxlfs,
const struct cxl_mbox_get_feat_in *feat_in;
u16 offset, count, return_code;
size_t out_size = *out_len;
+ ssize_t data_size;
if (rpc_in->op_size != sizeof(*feat_in))
return ERR_PTR(-EINVAL);
@@ -482,16 +489,17 @@ static void *cxlctl_get_feature(struct cxl_features_state *cxlfs,
if (!rpc_out)
return ERR_PTR(-ENOMEM);
- out_size = cxl_get_feature(cxl_mbox, &feat_in->uuid,
- feat_in->selection, rpc_out->payload,
- count, offset, &return_code);
+ data_size = cxl_get_feature(cxl_mbox, &feat_in->uuid,
+ feat_in->selection, rpc_out->payload,
+ count, offset, &return_code);
*out_len = sizeof(struct fwctl_rpc_cxl_out);
- if (!out_size) {
+ if (data_size <= 0) {
rpc_out->size = 0;
rpc_out->retval = return_code;
return no_free_ptr(rpc_out);
}
+ out_size = data_size;
rpc_out->size = out_size;
rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
*out_len += out_size;
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 2/6] cxl/region: Scan all partitions for unmapped poison
2026-08-12 11:21 [PATCH v4 0/6] cxl: Sashiko bug fixes Richard Cheng
2026-08-12 11:21 ` [PATCH v4 1/6] cxl/features: Reject feature offset that overflows 16-bit field Richard Cheng
@ 2026-08-12 11:21 ` Richard Cheng
2026-08-12 11:21 ` [PATCH v4 3/6] cxl/region: Don't leak tolerated RAM -EFAULT from unmapped poison scan Richard Cheng
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Richard Cheng @ 2026-08-12 11:21 UTC (permalink / raw)
To: dave, jic23, dave.jiang, alison.schofield, vishal.l.verma
Cc: iweiny, ming.li, gourry, rrichter, linux-cxl, linux-kernel, kees,
newtonl, kristinc, kaihengf, kobak, Richard Cheng
cxl_get_poison_unmapped() sweeps the unmapped tail of each partition
from ctx->part onward. A fully-mapped partition has no unmapped tail,
it's a normal per-partition state, but the loop treated it with break,
aborting the whole sweep and silently skipping unmapped poison in all
later partition. Use continue so a fully-mapped partition is skipped and
later partitions are still scanned.
Fixes: be5cbd0840275 ("cxl: Kill enum cxl_decoder_mode")
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Tested-by: Alison Schofield <alison.schofield@intel.com>
Signed-off-by: Richard Cheng <icheng@nvidia.com>
---
Changelog:
v1->v2:
- Tweak commit message
---
drivers/cxl/core/region.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 27e63e6dab7c..b03f30c04d35 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2928,7 +2928,7 @@ static int cxl_get_poison_unmapped(struct cxl_memdev *cxlmd,
offset = res->start;
length = res->end - offset + 1;
if (!length)
- break;
+ continue;
rc = cxl_mem_get_poison(cxlmd, offset, length, NULL);
if (rc == -EFAULT && cxlds->part[i].mode == CXL_PARTMODE_RAM)
continue;
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 3/6] cxl/region: Don't leak tolerated RAM -EFAULT from unmapped poison scan
2026-08-12 11:21 [PATCH v4 0/6] cxl: Sashiko bug fixes Richard Cheng
2026-08-12 11:21 ` [PATCH v4 1/6] cxl/features: Reject feature offset that overflows 16-bit field Richard Cheng
2026-08-12 11:21 ` [PATCH v4 2/6] cxl/region: Scan all partitions for unmapped poison Richard Cheng
@ 2026-08-12 11:21 ` Richard Cheng
2026-08-12 12:08 ` sashiko-bot
2026-08-12 11:21 ` [PATCH v4 4/6] cxl/region: Start unmapped poison scan at the committed decoder boundary Richard Cheng
` (2 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Richard Cheng @ 2026-08-12 11:21 UTC (permalink / raw)
To: dave, jic23, dave.jiang, alison.schofield, vishal.l.verma
Cc: iweiny, ming.li, gourry, rrichter, linux-cxl, linux-kernel, kees,
newtonl, kristinc, kaihengf, kobak, Richard Cheng
cxl_get_poison_unmapped() tolerates the -EFAULT a RAM partition returns
for Get Poison List by skipping that partition, but left rc holding the
error. If the tolerated RAM fault was the last poison query before the
loop ended, the function returned a spurious -EFAULT and the poison-list
read failed even though enumeration succeeded. Reset rc to 0 when
tolerating the fault, matching poison_by_decoder().
Fixes: be5cbd0840275 ("cxl: Kill enum cxl_decoder_mode")
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Richard Cheng <icheng@nvidia.com>
---
drivers/cxl/core/region.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index b03f30c04d35..ddf12075b95c 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2930,8 +2930,10 @@ static int cxl_get_poison_unmapped(struct cxl_memdev *cxlmd,
if (!length)
continue;
rc = cxl_mem_get_poison(cxlmd, offset, length, NULL);
- if (rc == -EFAULT && cxlds->part[i].mode == CXL_PARTMODE_RAM)
+ if (rc == -EFAULT && cxlds->part[i].mode == CXL_PARTMODE_RAM) {
+ rc = 0;
continue;
+ }
if (rc)
break;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 4/6] cxl/region: Start unmapped poison scan at the committed decoder boundary
2026-08-12 11:21 [PATCH v4 0/6] cxl: Sashiko bug fixes Richard Cheng
` (2 preceding siblings ...)
2026-08-12 11:21 ` [PATCH v4 3/6] cxl/region: Don't leak tolerated RAM -EFAULT from unmapped poison scan Richard Cheng
@ 2026-08-12 11:21 ` Richard Cheng
2026-08-12 11:21 ` [PATCH v4 5/6] cxl/memdev: Don't overwrite the error from an earlier partition poison query Richard Cheng
2026-08-12 11:21 ` [PATCH v4 6/6] cxl/region: Reject poison scan for decoder without a partition Richard Cheng
5 siblings, 0 replies; 10+ messages in thread
From: Richard Cheng @ 2026-08-12 11:21 UTC (permalink / raw)
To: dave, jic23, dave.jiang, alison.schofield, vishal.l.verma
Cc: iweiny, ming.li, gourry, rrichter, linux-cxl, linux-kernel, kees,
newtonl, kristinc, kaihengf, kobak, Richard Cheng
poison_by_decoder() stops at the last committed decoder and records the
handoff in ctx->offset, but cxl_get_poison_unmapped() ignores it and
starts after the highest DPA allocation instead. Allocation exist for
uncommitted decoders too, so their DPA is skipped by both phases and
poison there is never reported. Resume the scan at ctx->offset, and scan
later partitions in full, restoring the pre-rewrite behavior.
Fixes: be5cbd084027 ("cxl: Kill enum cxl_decoder_mode")
Signed-off-by: Richard Cheng <icheng@nvidia.com>
---
Changelog:
v1->v2:
- New added patch ( sashiko's report )
---
drivers/cxl/core/region.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index ddf12075b95c..b7dc5d4988da 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2907,7 +2907,6 @@ static int cxl_get_poison_unmapped(struct cxl_memdev *cxlmd,
{
struct cxl_dev_state *cxlds = cxlmd->cxlds;
const struct resource *res;
- struct resource *p, *last;
u64 offset, length;
int rc = 0;
@@ -2920,10 +2919,8 @@ static int cxl_get_poison_unmapped(struct cxl_memdev *cxlmd,
*/
for (int i = ctx->part; i < cxlds->nr_partitions; i++) {
res = &cxlds->part[i].res;
- for (p = res->child, last = NULL; p; p = p->sibling)
- last = p;
- if (last)
- offset = last->end + 1;
+ if (i == ctx->part)
+ offset = ctx->offset;
else
offset = res->start;
length = res->end - offset + 1;
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 5/6] cxl/memdev: Don't overwrite the error from an earlier partition poison query
2026-08-12 11:21 [PATCH v4 0/6] cxl: Sashiko bug fixes Richard Cheng
` (3 preceding siblings ...)
2026-08-12 11:21 ` [PATCH v4 4/6] cxl/region: Start unmapped poison scan at the committed decoder boundary Richard Cheng
@ 2026-08-12 11:21 ` Richard Cheng
2026-08-12 11:21 ` [PATCH v4 6/6] cxl/region: Reject poison scan for decoder without a partition Richard Cheng
5 siblings, 0 replies; 10+ messages in thread
From: Richard Cheng @ 2026-08-12 11:21 UTC (permalink / raw)
To: dave, jic23, dave.jiang, alison.schofield, vishal.l.verma
Cc: iweiny, ming.li, gourry, rrichter, linux-cxl, linux-kernel, kees,
newtonl, kristinc, kaihengf, kobak, Richard Cheng
cxl_get_poison_by_memdev() queries Get Poison List per partition but
never checks the result inside the loop, so a later partition's success
overwrites an earlier partition's failure and the whole scan reports
success while that partition's poison went unlisted. Before the loop
conversion the PMEM query returned early on error. Stop the loop on any
error not already tolerated as a RAM -EFAULT.
Fixes: be5cbd084027 ("cxl: Kill enum cxl_decoder_mode")
Signed-off-by: Richard Cheng <icheng@nvidia.com>
---
Changelog:
v1->v2:
- New added patch ( sashiko-bot's report )
---
drivers/cxl/core/memdev.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index b3419df586b9..e39b3d13fd56 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -231,6 +231,8 @@ static int cxl_get_poison_by_memdev(struct cxl_memdev *cxlmd)
*/
if (rc == -EFAULT && cxlds->part[i].mode == CXL_PARTMODE_RAM)
rc = 0;
+ if (rc)
+ break;
}
return rc;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 6/6] cxl/region: Reject poison scan for decoder without a partition
2026-08-12 11:21 [PATCH v4 0/6] cxl: Sashiko bug fixes Richard Cheng
` (4 preceding siblings ...)
2026-08-12 11:21 ` [PATCH v4 5/6] cxl/memdev: Don't overwrite the error from an earlier partition poison query Richard Cheng
@ 2026-08-12 11:21 ` Richard Cheng
2026-08-12 12:41 ` sashiko-bot
5 siblings, 1 reply; 10+ messages in thread
From: Richard Cheng @ 2026-08-12 11:21 UTC (permalink / raw)
To: dave, jic23, dave.jiang, alison.schofield, vishal.l.verma
Cc: iweiny, ming.li, gourry, rrichter, linux-cxl, linux-kernel, kees,
newtonl, kristinc, kaihengf, kobak, Richard Cheng
__cxl_dpa_reserve() may leave cxled->part at -1 when a decoder's DPA
range doesn't map to any reported partition, while still keeping
dpa_res. poison_by_decoder() then indexes cxlds->part[-1], causing an
out-of-bounds read when poison collection is triggered.
Return -ENODEV before accessing the partition array when no partition was
assigned.
Fixes: be5cbd084027 ("cxl: Kill enum cxl_decoder_mode")
Signed-off-by: Richard Cheng <icheng@nvidia.com>
---
drivers/cxl/core/region.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index b7dc5d4988da..afe3fb57b7fe 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2954,6 +2954,8 @@ static int poison_by_decoder(struct device *dev, void *arg)
cxled = to_cxl_endpoint_decoder(dev);
if (!cxled->dpa_res)
return rc;
+ if (cxled->part < 0)
+ return -ENODEV;
cxlmd = cxled_to_memdev(cxled);
cxlds = cxlmd->cxlds;
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v4 1/6] cxl/features: Reject feature offset that overflows 16-bit field
2026-08-12 11:21 ` [PATCH v4 1/6] cxl/features: Reject feature offset that overflows 16-bit field Richard Cheng
@ 2026-08-12 11:52 ` sashiko-bot
0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-08-12 11:52 UTC (permalink / raw)
To: Richard Cheng; +Cc: linux-cxl
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] fwctl ioctls falsely report SUCCESS to userspace when CXL mailbox transport encounters an internal error.
--
--- Patch [1]: [PATCH v4 1/6] cxl/features: Reject feature offset that overflows 16-bit field ---
commit 758deff635a1582bb94f5fac18c817ddd4966bdb
Author: Richard Cheng <icheng@nvidia.com>
cxl/features: Reject feature offset that overflows 16-bit field
This patch validates that the transfer size does not exceed the remaining 16-bit
feature range to prevent truncation when building mailbox command offsets. It
also changes cxl_get_feature() to return ssize_t so invalid input and mailbox
failures are reported as negative errno. Finally, it updates the EDAC callers
to handle negative results.
> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
> index ba6d2a5acb74a..8d44ce8294978 100644
> --- a/drivers/cxl/core/features.c
> +++ b/drivers/cxl/core/features.c
[ ... ]
> @@ -259,7 +262,7 @@ size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
> if (rc < 0 || !mbox_cmd.size_out) {
> if (return_code)
> *return_code = mbox_cmd.return_code;
> - return 0;
> + return rc < 0 ? rc : -EIO;
> }
[Severity: High]
This isn't a bug introduced by this patch, but if cxl_internal_send_cmd()
fails with an OS-level error (rc < 0), it won't populate
mbox_cmd.return_code. Since mbox_cmd was initialized as a compound literal,
doesn't this set *return_code to 0 (CXL_MBOX_CMD_RC_SUCCESS)?
When this happens, cxlctl_get_feature() will absorb the negative error code
and pass the zeroed return_code back to fwctl:
drivers/cxl/core/features.c:cxlctl_get_feature() {
...
data_size = cxl_get_feature(..., &return_code);
*out_len = sizeof(struct fwctl_rpc_cxl_out);
if (data_size <= 0) {
rpc_out->size = 0;
rpc_out->retval = return_code;
return no_free_ptr(rpc_out);
}
...
}
Does this result in fwctl ioctls falsely reporting SUCCESS to userspace when
the CXL mailbox transport encounters an internal error? This same pattern
appears to be present in cxl_set_feature() and cxlctl_set_feature() as well.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260812112107.56181-1-icheng@nvidia.com?part=1
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 3/6] cxl/region: Don't leak tolerated RAM -EFAULT from unmapped poison scan
2026-08-12 11:21 ` [PATCH v4 3/6] cxl/region: Don't leak tolerated RAM -EFAULT from unmapped poison scan Richard Cheng
@ 2026-08-12 12:08 ` sashiko-bot
0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-08-12 12:08 UTC (permalink / raw)
To: Richard Cheng; +Cc: linux-cxl
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] cxl_get_poison_by_memdev() fails to break the loop on error, potentially overwriting a failing return code with a success return code from a subsequent partition.
--
--- Patch [3]: [PATCH v4 3/6] cxl/region: Don't leak tolerated RAM -EFAULT from unmapped poison scan ---
commit a0d57b2595f3317a70e0887bd131f7b1df706fef
Author: Richard Cheng <icheng@nvidia.com>
cxl/region: Don't leak tolerated RAM -EFAULT from unmapped poison scan
cxl_get_poison_unmapped() tolerates the -EFAULT a RAM partition returns
for Get Poison List by skipping that partition, but left rc holding the
error. If the tolerated RAM fault was the last poison query before the
loop ended, the function returned a spurious -EFAULT and the poison-list
read failed even though enumeration succeeded. Reset rc to 0 when
tolerating the fault, matching poison_by_decoder().
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index b03f30c04d350..ddf12075b95c0 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -2930,8 +2930,10 @@ static int cxl_get_poison_unmapped(struct cxl_memdev *cxlmd,
> if (!length)
> continue;
> rc = cxl_mem_get_poison(cxlmd, offset, length, NULL);
> - if (rc == -EFAULT && cxlds->part[i].mode == CXL_PARTMODE_RAM)
> + if (rc == -EFAULT && cxlds->part[i].mode == CXL_PARTMODE_RAM) {
> + rc = 0;
> continue;
> + }
> if (rc)
> break;
> }
[Severity: High]
This isn't a bug introduced by this patch, but was introduced in an earlier
commit be5cbd0840275 ("cxl: Kill enum cxl_decoder_mode"). Seeing the loop
here made me look at similar code in drivers/cxl/core/memdev.c.
Does cxl_get_poison_by_memdev() fail to break the loop on error?
drivers/cxl/core/memdev.c:cxl_get_poison_by_memdev() {
for (int i = 0; i < cxlds->nr_partitions; i++) {
const struct resource *res = &cxlds->part[i].res;
offset = res->start;
length = resource_size(res);
rc = cxl_mem_get_poison(cxlmd, offset, length, NULL);
/*
* Invalid Physical Address is not an error for
* volatile addresses. Device support is optional.
*/
if (rc == -EFAULT && cxlds->part[i].mode == CXL_PARTMODE_RAM)
rc = 0;
}
}
If cxl_mem_get_poison() fails for an early partition (like partition 0) due to
a hardware mailbox timeout and returns an error like -EIO, rc is set to the
error code. Since the loop lacks an if (rc) break; statement, it proceeds to
the next partition.
If the subsequent partition succeeds, rc is overwritten with 0, and the
function returns success. This masks the failure on partition 0 and leaves the
kernel unaware of poisoned memory.
Could this missing break statement lead to unhandled machine checks and
potential data corruption if that poisoned memory is accessed?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260812112107.56181-1-icheng@nvidia.com?part=3
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 6/6] cxl/region: Reject poison scan for decoder without a partition
2026-08-12 11:21 ` [PATCH v4 6/6] cxl/region: Reject poison scan for decoder without a partition Richard Cheng
@ 2026-08-12 12:41 ` sashiko-bot
0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-08-12 12:41 UTC (permalink / raw)
To: Richard Cheng; +Cc: linux-cxl
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Returning `-ENODEV` for an unmapped partition aborts the entire poison collection iteration.
--
--- Patch [6]: [PATCH v4 6/6] cxl/region: Reject poison scan for decoder without a partition ---
commit 8cb40391df3fd49e0cd36f0f034423d0470da73b
Author: Richard Cheng <icheng@nvidia.com>
cxl/region: Reject poison scan for decoder without a partition
__cxl_dpa_reserve() may leave cxled->part at -1 when a decoder's DPA
range doesn't map to any reported partition, while still keeping
dpa_res. This commit returns -ENODEV before accessing the partition array
when no partition was assigned to avoid an out-of-bounds read.
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index b7dc5d4988da7..afe3fb57b7fe2 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -2954,6 +2954,8 @@ static int poison_by_decoder(struct device *dev, void *arg)
> cxled = to_cxl_endpoint_decoder(dev);
> if (!cxled->dpa_res)
> return rc;
> + if (cxled->part < 0)
> + return -ENODEV;
[Severity: Medium]
Since poison_by_decoder() is used as an iterator callback for
device_for_each_child(), does returning -ENODEV here prematurely abort the
entire poison collection iteration?
If any decoder on the port has an unmapped partition, returning a negative
error code would halt the traversal. The sysfs trigger would then fail with
-ENODEV, skipping poison collection for all subsequent decoders.
Would it be better to return 0 here to just skip the unmapped decoder and
continue iterating over the remaining ones?
>
> cxlmd = cxled_to_memdev(cxled);
> cxlds = cxlmd->cxlds;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260812112107.56181-1-icheng@nvidia.com?part=6
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-08-12 12:41 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-12 11:21 [PATCH v4 0/6] cxl: Sashiko bug fixes Richard Cheng
2026-08-12 11:21 ` [PATCH v4 1/6] cxl/features: Reject feature offset that overflows 16-bit field Richard Cheng
2026-08-12 11:52 ` sashiko-bot
2026-08-12 11:21 ` [PATCH v4 2/6] cxl/region: Scan all partitions for unmapped poison Richard Cheng
2026-08-12 11:21 ` [PATCH v4 3/6] cxl/region: Don't leak tolerated RAM -EFAULT from unmapped poison scan Richard Cheng
2026-08-12 12:08 ` sashiko-bot
2026-08-12 11:21 ` [PATCH v4 4/6] cxl/region: Start unmapped poison scan at the committed decoder boundary Richard Cheng
2026-08-12 11:21 ` [PATCH v4 5/6] cxl/memdev: Don't overwrite the error from an earlier partition poison query Richard Cheng
2026-08-12 11:21 ` [PATCH v4 6/6] cxl/region: Reject poison scan for decoder without a partition Richard Cheng
2026-08-12 12:41 ` 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.