Re: [PATCH] cxl/region: Fix out of bounds access in cxl_cancel_auto_attach()
From: Dave Jiang
Date: Wed May 20 2026 - 11:10:43 EST
On 5/20/26 5:30 AM, Li Ming wrote:
>
> 在 2026/5/20 01:18, Dave Jiang 写道:
>>
>> On 5/19/26 6:23 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 -ENXIO in
>> It can be set to other error codes I think? I would just s/-ENXIO/negative errno/
> Sure, Will do that.
>>
>>> 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.
>> Does the comment in cxl_region_sort_targets() need to be updated with the new changes?
>
> I'm not sure how to update the comment in cxl_region_sort_targets(). Any suggestion?
idk if we should just drop it entirely since the comment is no longer true. At least that second part. Alison?
>
>
> Ming
>
>>
>>> Fixes: 87805c32e6ad ("cxl/region: Fix use-after-free from auto assembly failure")
>>> Signed-off-by: Li Ming <ming.li@xxxxxxxxxxxx>
>> The rest LGTM
>>
>> DJ
>>
>>> ---
>>> drivers/cxl/core/region.c | 35 ++++++++++++++++-------------------
>>> 1 file changed, 16 insertions(+), 19 deletions(-)
>>>
>>> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
>>> index e50dc716d4e8..551228bc91f5 100644
>>> --- a/drivers/cxl/core/region.c
>>> +++ b/drivers/cxl/core/region.c
>>> @@ -2202,18 +2202,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 +2234,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 *
>>>
>>> ---
>>> base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
>>> change-id: 20260519-fix_out_of_bounds_access-8838759ee5a6
>>>
>>> Best regards,