Commit a3483ee7 authored by Huang Ying's avatar Huang Ying Committed by Dave Jiang

cxl/region: Fix a race condition in memory hotplug notifier

In the memory hotplug notifier function of the CXL region,
cxl_region_perf_attrs_callback(), the node ID is obtained by checking
the host address range of the region. However, the address range
information is not available when the region is registered in
devm_cxl_add_region(). Additionally, this information may be removed
or added under the protection of cxl_region_rwsem during runtime. If
the memory notifier is called for nodes other than that backed by the
region, a race condition may occur, potentially leading to a NULL
dereference or an invalid address range.

The race condition is addressed by checking the availability of the
address range information under the protection of cxl_region_rwsem. To
enhance code readability and use guard(), the relevant code has been
moved into a newly added function: cxl_region_nid().

Fixes: 067353a4 ("cxl/region: Add memory hotplug notifier for cxl region")
Signed-off-by: default avatarHuang, Ying <ying.huang@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Alison Schofield <alison.schofield@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Bharata B Rao <bharata@amd.com>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://patch.msgid.link/20240618084639.1419629-2-ying.huang@intel.comSigned-off-by: default avatarDave Jiang <dave.jiang@intel.com>
parent a0caa197
...@@ -2304,14 +2304,25 @@ static bool cxl_region_update_coordinates(struct cxl_region *cxlr, int nid) ...@@ -2304,14 +2304,25 @@ static bool cxl_region_update_coordinates(struct cxl_region *cxlr, int nid)
return true; return true;
} }
static int cxl_region_nid(struct cxl_region *cxlr)
{
struct cxl_region_params *p = &cxlr->params;
struct cxl_endpoint_decoder *cxled;
struct cxl_decoder *cxld;
guard(rwsem_read)(&cxl_region_rwsem);
cxled = p->targets[0];
if (!cxled)
return NUMA_NO_NODE;
cxld = &cxled->cxld;
return phys_to_target_node(cxld->hpa_range.start);
}
static int cxl_region_perf_attrs_callback(struct notifier_block *nb, static int cxl_region_perf_attrs_callback(struct notifier_block *nb,
unsigned long action, void *arg) unsigned long action, void *arg)
{ {
struct cxl_region *cxlr = container_of(nb, struct cxl_region, struct cxl_region *cxlr = container_of(nb, struct cxl_region,
memory_notifier); memory_notifier);
struct cxl_region_params *p = &cxlr->params;
struct cxl_endpoint_decoder *cxled = p->targets[0];
struct cxl_decoder *cxld = &cxled->cxld;
struct memory_notify *mnb = arg; struct memory_notify *mnb = arg;
int nid = mnb->status_change_nid; int nid = mnb->status_change_nid;
int region_nid; int region_nid;
...@@ -2319,7 +2330,7 @@ static int cxl_region_perf_attrs_callback(struct notifier_block *nb, ...@@ -2319,7 +2330,7 @@ static int cxl_region_perf_attrs_callback(struct notifier_block *nb,
if (nid == NUMA_NO_NODE || action != MEM_ONLINE) if (nid == NUMA_NO_NODE || action != MEM_ONLINE)
return NOTIFY_DONE; return NOTIFY_DONE;
region_nid = phys_to_target_node(cxld->hpa_range.start); region_nid = cxl_region_nid(cxlr);
if (nid != region_nid) if (nid != region_nid)
return NOTIFY_DONE; return NOTIFY_DONE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment