* [PATCH v3 1/1] cxl/region: Fix out-of-bounds access in cxl_cancel_auto_attach()
@ 2026-05-29 13:25 Li Ming
2026-05-29 15:25 ` Alison Schofield
2026-05-29 16:39 ` Dave Jiang
0 siblings, 2 replies; 3+ messages in thread
From: Li Ming @ 2026-05-29 13:25 UTC (permalink / raw)
To: dave, jic23, dave.jiang, alison.schofield, vishal.l.verma,
ira.weiny, djbw
Cc: linux-cxl, linux-kernel
In cxl_cancel_auto_attach(), it assumes cxled->pos is a valid index for
accessing p->targets[]. However, cxled->pos can be set to negative errno
in cxl_region_sort_targets() if cxl_calc_interleave_pos() fails. This
causes the driver to use a negative index to access p->targets[],
resulting in out-of-bounds access.
Fix it by walking p->targets[] instead of using cxled->pos directly.
Fixes: 87805c32e6ad ("cxl/region: Fix use-after-free from auto assembly failure")
Signed-off-by: Li Ming <ming.li@zohomail.com>
---
Changes from v2:
- Revert "Fix potential 'hole' issue." changes. (Alison)
Changes from v1:
- Update commit log. (Dave)
- Update comment in cxl_region_sort_targets(). (Dave)
- Fix potential 'hole' issue. (Alison & Sashiko review)
---
drivers/cxl/core/region.c | 40 +++++++++++++++++++--------------------
1 file changed, 19 insertions(+), 21 deletions(-)
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index e50dc716d4e8..eb96cb3cae83 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2011,8 +2011,9 @@ static int cxl_region_sort_targets(struct cxl_region *cxlr)
cxled->pos = cxl_calc_interleave_pos(cxled, &cxlr->hpa_range);
/*
* Record that sorting failed, but still continue to calc
- * cxled->pos so that follow-on code paths can reliably
- * do p->targets[cxled->pos] to self-reference their entry.
+ * cxled->pos so that cxl_calc_interleave_pos() emits its
+ * dev_dbg() for every member. which is useful for auto
+ * discovery debug.
*/
if (cxled->pos < 0)
rc = -ENXIO;
@@ -2202,18 +2203,30 @@ static int cxl_region_attach(struct cxl_region *cxlr,
return 0;
}
-static int cxl_region_by_target(struct device *dev, const void *data)
+static int cxl_region_remove_target(struct device *dev, void *data)
{
- const struct cxl_endpoint_decoder *cxled = data;
+ struct cxl_endpoint_decoder *cxled = data;
struct cxl_region_params *p;
struct cxl_region *cxlr;
+ int i;
if (!is_cxl_region(dev))
return 0;
cxlr = to_cxl_region(dev);
p = &cxlr->params;
- return p->targets[cxled->pos] == cxled;
+ for (i = 0; i < p->nr_targets; i++) {
+ if (p->targets[i] == cxled) {
+ p->nr_targets--;
+ cxled->state = CXL_DECODER_STATE_AUTO;
+ cxled->pos = -1;
+ p->targets[i] = NULL;
+
+ return 1;
+ }
+ }
+
+ return 0;
}
/*
@@ -2222,25 +2235,10 @@ static int cxl_region_by_target(struct device *dev, const void *data)
*/
static void cxl_cancel_auto_attach(struct cxl_endpoint_decoder *cxled)
{
- struct cxl_region_params *p;
- struct cxl_region *cxlr;
- int pos = cxled->pos;
-
if (cxled->state != CXL_DECODER_STATE_AUTO_STAGED)
return;
- struct device *dev __free(put_device) =
- bus_find_device(&cxl_bus_type, NULL, cxled, cxl_region_by_target);
- if (!dev)
- return;
-
- cxlr = to_cxl_region(dev);
- p = &cxlr->params;
-
- p->nr_targets--;
- cxled->state = CXL_DECODER_STATE_AUTO;
- cxled->pos = -1;
- p->targets[pos] = NULL;
+ bus_for_each_dev(&cxl_bus_type, NULL, cxled, cxl_region_remove_target);
}
static struct cxl_region *
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v3 1/1] cxl/region: Fix out-of-bounds access in cxl_cancel_auto_attach()
2026-05-29 13:25 [PATCH v3 1/1] cxl/region: Fix out-of-bounds access in cxl_cancel_auto_attach() Li Ming
@ 2026-05-29 15:25 ` Alison Schofield
2026-05-29 16:39 ` Dave Jiang
1 sibling, 0 replies; 3+ messages in thread
From: Alison Schofield @ 2026-05-29 15:25 UTC (permalink / raw)
To: Li Ming
Cc: dave, jic23, dave.jiang, vishal.l.verma, ira.weiny, djbw,
linux-cxl, linux-kernel
On Fri, May 29, 2026 at 09:25:33PM +0800, Li Ming wrote:
> In cxl_cancel_auto_attach(), it assumes cxled->pos is a valid index for
> accessing p->targets[]. However, cxled->pos can be set to negative errno
> in cxl_region_sort_targets() if cxl_calc_interleave_pos() fails. This
> causes the driver to use a negative index to access p->targets[],
> resulting in out-of-bounds access.
>
> Fix it by walking p->targets[] instead of using cxled->pos directly.
>
> Fixes: 87805c32e6ad ("cxl/region: Fix use-after-free from auto assembly failure")
> Signed-off-by: Li Ming <ming.li@zohomail.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
> ---
> Changes from v2:
> - Revert "Fix potential 'hole' issue." changes. (Alison)
>
> Changes from v1:
> - Update commit log. (Dave)
> - Update comment in cxl_region_sort_targets(). (Dave)
> - Fix potential 'hole' issue. (Alison & Sashiko review)
> ---
> drivers/cxl/core/region.c | 40 +++++++++++++++++++--------------------
> 1 file changed, 19 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index e50dc716d4e8..eb96cb3cae83 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -2011,8 +2011,9 @@ static int cxl_region_sort_targets(struct cxl_region *cxlr)
> cxled->pos = cxl_calc_interleave_pos(cxled, &cxlr->hpa_range);
> /*
> * Record that sorting failed, but still continue to calc
> - * cxled->pos so that follow-on code paths can reliably
> - * do p->targets[cxled->pos] to self-reference their entry.
> + * cxled->pos so that cxl_calc_interleave_pos() emits its
> + * dev_dbg() for every member. which is useful for auto
> + * discovery debug.
> */
> if (cxled->pos < 0)
> rc = -ENXIO;
> @@ -2202,18 +2203,30 @@ static int cxl_region_attach(struct cxl_region *cxlr,
> return 0;
> }
>
> -static int cxl_region_by_target(struct device *dev, const void *data)
> +static int cxl_region_remove_target(struct device *dev, void *data)
> {
> - const struct cxl_endpoint_decoder *cxled = data;
> + struct cxl_endpoint_decoder *cxled = data;
> struct cxl_region_params *p;
> struct cxl_region *cxlr;
> + int i;
>
> if (!is_cxl_region(dev))
> return 0;
>
> cxlr = to_cxl_region(dev);
> p = &cxlr->params;
> - return p->targets[cxled->pos] == cxled;
> + for (i = 0; i < p->nr_targets; i++) {
> + if (p->targets[i] == cxled) {
> + p->nr_targets--;
> + cxled->state = CXL_DECODER_STATE_AUTO;
> + cxled->pos = -1;
> + p->targets[i] = NULL;
> +
> + return 1;
> + }
> + }
> +
> + return 0;
> }
>
> /*
> @@ -2222,25 +2235,10 @@ static int cxl_region_by_target(struct device *dev, const void *data)
> */
> static void cxl_cancel_auto_attach(struct cxl_endpoint_decoder *cxled)
> {
> - struct cxl_region_params *p;
> - struct cxl_region *cxlr;
> - int pos = cxled->pos;
> -
> if (cxled->state != CXL_DECODER_STATE_AUTO_STAGED)
> return;
>
> - struct device *dev __free(put_device) =
> - bus_find_device(&cxl_bus_type, NULL, cxled, cxl_region_by_target);
> - if (!dev)
> - return;
> -
> - cxlr = to_cxl_region(dev);
> - p = &cxlr->params;
> -
> - p->nr_targets--;
> - cxled->state = CXL_DECODER_STATE_AUTO;
> - cxled->pos = -1;
> - p->targets[pos] = NULL;
> + bus_for_each_dev(&cxl_bus_type, NULL, cxled, cxl_region_remove_target);
> }
>
> static struct cxl_region *
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v3 1/1] cxl/region: Fix out-of-bounds access in cxl_cancel_auto_attach()
2026-05-29 13:25 [PATCH v3 1/1] cxl/region: Fix out-of-bounds access in cxl_cancel_auto_attach() Li Ming
2026-05-29 15:25 ` Alison Schofield
@ 2026-05-29 16:39 ` Dave Jiang
1 sibling, 0 replies; 3+ messages in thread
From: Dave Jiang @ 2026-05-29 16:39 UTC (permalink / raw)
To: Li Ming, dave, jic23, alison.schofield, vishal.l.verma, ira.weiny, djbw
Cc: linux-cxl, linux-kernel
On 5/29/26 6:25 AM, Li Ming wrote:
> In cxl_cancel_auto_attach(), it assumes cxled->pos is a valid index for
> accessing p->targets[]. However, cxled->pos can be set to negative errno
> in cxl_region_sort_targets() if cxl_calc_interleave_pos() fails. This
> causes the driver to use a negative index to access p->targets[],
> resulting in out-of-bounds access.
>
> Fix it by walking p->targets[] instead of using cxled->pos directly.
>
> Fixes: 87805c32e6ad ("cxl/region: Fix use-after-free from auto assembly failure")
> Signed-off-by: Li Ming <ming.li@zohomail.com>
Applied to cxl/next
809ccef5385fa1779c7db3de43272f3fc6a87a45
> ---
> Changes from v2:
> - Revert "Fix potential 'hole' issue." changes. (Alison)
>
> Changes from v1:
> - Update commit log. (Dave)
> - Update comment in cxl_region_sort_targets(). (Dave)
> - Fix potential 'hole' issue. (Alison & Sashiko review)
> ---
> drivers/cxl/core/region.c | 40 +++++++++++++++++++--------------------
> 1 file changed, 19 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index e50dc716d4e8..eb96cb3cae83 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -2011,8 +2011,9 @@ static int cxl_region_sort_targets(struct cxl_region *cxlr)
> cxled->pos = cxl_calc_interleave_pos(cxled, &cxlr->hpa_range);
> /*
> * Record that sorting failed, but still continue to calc
> - * cxled->pos so that follow-on code paths can reliably
> - * do p->targets[cxled->pos] to self-reference their entry.
> + * cxled->pos so that cxl_calc_interleave_pos() emits its
> + * dev_dbg() for every member. which is useful for auto
> + * discovery debug.
> */
> if (cxled->pos < 0)
> rc = -ENXIO;
> @@ -2202,18 +2203,30 @@ static int cxl_region_attach(struct cxl_region *cxlr,
> return 0;
> }
>
> -static int cxl_region_by_target(struct device *dev, const void *data)
> +static int cxl_region_remove_target(struct device *dev, void *data)
> {
> - const struct cxl_endpoint_decoder *cxled = data;
> + struct cxl_endpoint_decoder *cxled = data;
> struct cxl_region_params *p;
> struct cxl_region *cxlr;
> + int i;
>
> if (!is_cxl_region(dev))
> return 0;
>
> cxlr = to_cxl_region(dev);
> p = &cxlr->params;
> - return p->targets[cxled->pos] == cxled;
> + for (i = 0; i < p->nr_targets; i++) {
> + if (p->targets[i] == cxled) {
> + p->nr_targets--;
> + cxled->state = CXL_DECODER_STATE_AUTO;
> + cxled->pos = -1;
> + p->targets[i] = NULL;
> +
> + return 1;
> + }
> + }
> +
> + return 0;
> }
>
> /*
> @@ -2222,25 +2235,10 @@ static int cxl_region_by_target(struct device *dev, const void *data)
> */
> static void cxl_cancel_auto_attach(struct cxl_endpoint_decoder *cxled)
> {
> - struct cxl_region_params *p;
> - struct cxl_region *cxlr;
> - int pos = cxled->pos;
> -
> if (cxled->state != CXL_DECODER_STATE_AUTO_STAGED)
> return;
>
> - struct device *dev __free(put_device) =
> - bus_find_device(&cxl_bus_type, NULL, cxled, cxl_region_by_target);
> - if (!dev)
> - return;
> -
> - cxlr = to_cxl_region(dev);
> - p = &cxlr->params;
> -
> - p->nr_targets--;
> - cxled->state = CXL_DECODER_STATE_AUTO;
> - cxled->pos = -1;
> - p->targets[pos] = NULL;
> + bus_for_each_dev(&cxl_bus_type, NULL, cxled, cxl_region_remove_target);
> }
>
> static struct cxl_region *
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-05-29 16:39 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-29 13:25 [PATCH v3 1/1] cxl/region: Fix out-of-bounds access in cxl_cancel_auto_attach() Li Ming
2026-05-29 15:25 ` Alison Schofield
2026-05-29 16:39 ` Dave Jiang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®