[PATCH 7/8] cxl/mce: Validate the memdev and endpoint before use

Guixin Liu <[email protected]>
Newsgroups org.kernel.vger.linux-cxl
Message-ID <[email protected]>
cxl_handle_mce() dereferences mds->cxlds.cxlmd and treats cxlmd->endpoint
as a plain pointer. Neither holds at all times:

- The notifier is registered by cxl_memdev_state_create() from
  cxl_pci_probe(), while cxlds->cxlmd is only published later by
  devm_cxl_add_memdev(). An MCE delivered in that window dereferences a
  NULL cxlmd.

- cxl_memdev_alloc() initialises cxlmd->endpoint to ERR_PTR(-ENXIO). It
  stays that way until the cxl_mem driver adds the endpoint port in a
  separate probe, and forever if that probe never runs or fails before
  then. The existing "if (!endpoint)" test lets the error pointer
  through, and cxl_port_get_spa_cache_alias() only guards against NULL
  as well before walking endpoint->regions.

Check cxlmd for NULL before dereferencing it, and use IS_ERR_OR_NULL() on
the endpoint. delete_endpoint() stores a plain NULL, so the existing test
is only wrong about the error pointer.

Fixes: 516e5bd0b6bf ("cxl: Add mce notifier to emit aliased address for extended linear cache")
Signed-off-by: Guixin Liu <[email protected]>
---
 drivers/cxl/core/mce.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/cxl/core/mce.c b/drivers/cxl/core/mce.c
index ff8d078c6ca1..47566015eb00 100644
--- a/drivers/cxl/core/mce.c
+++ b/drivers/cxl/core/mce.c
@@ -13,7 +13,7 @@ static int cxl_handle_mce(struct notifier_block *nb, unsigned long val,
 	struct cxl_memdev_state *mds = container_of(nb, struct cxl_memdev_state,
 						    mce_notifier);
 	struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
-	struct cxl_port *endpoint = cxlmd->endpoint;
+	struct cxl_port *endpoint;
 	struct mce *mce = data;
 	u64 spa, spa_alias;
 	unsigned long pfn;
@@ -21,7 +21,11 @@ static int cxl_handle_mce(struct notifier_block *nb, unsigned long val,
 	if (!mce || !mce_usable_address(mce))
 		return NOTIFY_DONE;
 
-	if (!endpoint)
+	if (!cxlmd)
+		return NOTIFY_DONE;
+
+	endpoint = cxlmd->endpoint;
+	if (IS_ERR_OR_NULL(endpoint))
 		return NOTIFY_DONE;
 
 	spa = mce->addr & MCI_ADDR_PHYSADDR;
-- 
2.43.7
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.