From nobody Wed Jun 17 07:35:34 2026 Received: from mail-yx1-f53.google.com (mail-yx1-f53.google.com [74.125.224.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BD66D202F71 for ; Mon, 27 Apr 2026 03:26:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777260390; cv=none; b=O4AOl6ItdvUDjiiYLMbcWWOYvclZlC/KOSLY28QPD8ZC5/DNvilKaQcHl5apLm6x15/85+HGe7WV+6tYkdUyyIhTj5rrulXsEqurc782s1P3rQvisUrBx2b/WCh1jKaIGDuXX2BjzOfgpbGDduoG3ltm4eBZmf4AUfPlh3SIV2Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777260390; c=relaxed/simple; bh=o9u/OwTZbv2Jmv7Yqa1UMp6K0xAH19Dqu+osE5o1Pkw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gFINLJLv1ysM8y/qSMzggCnHGUTq73VNkKQpLlXSfFrL+hHjg8gfazB9UXbt+q/U3mHuC+dj55G2AUACw22yBQVAuY8gdoBz+a19lE0bCxQ/00y32U6MW12hFPZBPXO5awAckhufFWvMuHf5O8SbuG3Tx+mE6DjieO9P3RPMX5A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=sung-woo.kim; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=74.125.224.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=sung-woo.kim Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-yx1-f53.google.com with SMTP id 956f58d0204a3-650775f427eso10185967d50.2 for ; Sun, 26 Apr 2026 20:26:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777260388; x=1777865188; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=C5hxakvROgtrD8FVisml9LRgxf6CeSENy2gXMVuYHr4=; b=OGu7M07cKJy82Awdn3QIYiVxeYf9b41LMh3+amtobdG1KMBmqrBglPfOFM+QjWm3rz MEiVDUbkmZG6GYIoltJOFiwtHZFWe4u0mV+1y3eohSVUc77vsVxGAMDXU7DgjTqcAS2K maM3buEhvV0Mp4S3Jprw9sP7YbSbjwXUyKgyHKuWeVcjz8PN+4SXD7dCN8Frf/kwJH31 f7IUJUlFCkjsnSZK+jle+D0ExiZd6GxAec+UWpgNPrkSkwctuHjtsL4lM+Nys0gjXxd6 dzh/KaZ10yR824U2bKlPHcbELcsXfo/tAgVGJOl3H7yQJpEh9CzAGeUd997oD9WmDQY8 HjXw== X-Forwarded-Encrypted: i=1; AFNElJ+GFLAaBjLrYaZtSI+bgTz1cCniXgqZTh8UZqy6zq+CXgPKFyKQAk7zgnOhCBnuSEGctYw1jGjk/6InxoM=@vger.kernel.org X-Gm-Message-State: AOJu0YzrETULpFIRX8DBysf58chqxfogLGwemnKvnQy8SpxB8S5NlSnO 8V2n9IathCoVOPOYJJQxEssoR1d0pIO3+R6IcToDgRTk3e+HMbgfbfzK X-Gm-Gg: AeBDiesjyazfSQGNKvwXrctzdvrTMaG3wOoYArCuXOmDp13okYpt64zTMZtrDb733D4 Env9KvKyF3Hgv0moMz7T118GczDMj4r4lGuo3Uc2FLHYTw0L4ziAhO19FmiU+NNAjC8ow3ck+by zBKihHoZ7y3cD2rtPLKh8wjXfviR/kaafd5T4DR/JEKU2Y8pfOHmupx5ku5gzG5FfIgcfKBMAR0 s4+ZR/sY71bakIC1mkGMzmHQSgmoEF7Zs3ShI5g06fYZ1dc347bVce6X4tzE4T8qWYfeigDw5Xf 4hhREWN8XUtCZdj1Mb8lrl7PO5bktpFfLcMOrodjK91pBReAwqbPibaOHzqED8lEUT4hKGOdghX GbMo0Ygwy+r5xpZdzU9as62R+8fh+k1uKwBO+Z6nb047wKwOOp7dswnF6xMSXEsVL7zO9LQkHWu YmGdl6POauOWqQWxYYbQBY X-Received: by 2002:a53:ea84:0:b0:651:8d82:acc5 with SMTP id 956f58d0204a3-653108c0224mr29243595d50.26.1777260387798; Sun, 26 Apr 2026 20:26:27 -0700 (PDT) Received: from tofu.. ([128.210.0.165]) by smtp.googlemail.com with ESMTPSA id 956f58d0204a3-65314b26b56sm14087239d50.4.2026.04.26.20.26.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Apr 2026 20:26:26 -0700 (PDT) From: Sungwoo Kim To: Davidlohr Bueso , Jonathan Cameron , Dave Jiang , Alison Schofield , Vishal Verma , Ira Weiny , Dan Williams Cc: Dave Tian , Sungwoo Kim , linux-cxl@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/2] cxl/region: serialize devm action removal via scheduled work Date: Sun, 26 Apr 2026 23:20:09 -0400 Message-ID: <20260427032010.916681-4-iam@sung-woo.kim> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260427032010.916681-2-iam@sung-woo.kim> References: <20260427032010.916681-2-iam@sung-woo.kim> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" devm_remove_action() must be called (1) only once and (2) only if the device is still bound to a driver. However, several race conditions allow multiple calls to devm_remove_action(). For example, delete_region_store() and devres_release_all() can race [1]: CPU0 CPU1 devres_release_all() // take devres_lock remove_nodes(devres_head) // mv to local todo // drop devres_lock delete_region_store() cxlr =3D cxl_find_region_by_name= () // success devm_release_action(unregister_r= egion) devres_release() devres_remove() // hold devres_lock find_dr(devres_head) // do= es not find it WARN_ON(-ENOENT) release_nodes() // drain todo unregister_region(cxlr) // release() cb device_del() To prevent this, this patch introduces a new function, remove_devm_actions(), that safely performs devm_release_action(). remove_devm_actions() guarantees that devm_release_action() is called only once by guarding with a flag. Also, it checks if the device is still bound to a driver before calling devm_remove_action(). In order to check the binding, a device lock must be held. To do this, Dan suggested [2] using a workqueue, since a new work has no prior lock and is clean to acquire a device lock. [1] https://lore.kernel.org/linux-cxl/20260310183644.4rwc7ilmzy4t5xp6@offwo= rld/ [2] https://lore.kernel.org/linux-cxl/69b0a0f8bfb0b_213210026@dwillia2-mobl= 4.notmuch/ Suggested-by: Dan Williams Signed-off-by: Sungwoo Kim Reviewed-by: Jonathan Cameron --- drivers/cxl/core/port.c | 6 ++++++ drivers/cxl/core/region.c | 27 +++++++++++++++++++++++++++ drivers/cxl/cxl.h | 9 +++++++++ 3 files changed, 42 insertions(+) diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index c5aacd7054f1..2f142cea7f26 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -2305,6 +2305,12 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *c= xlmd) } EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, "CXL"); =20 +bool schedule_cxl_region_remove_devm_actions(struct cxl_region *cxlr) +{ + return queue_work(cxl_bus_wq, &cxlr->remove_work); +} +EXPORT_SYMBOL_NS_GPL(schedule_cxl_region_remove_devm_actions, "CXL"); + static void add_latency(struct access_coordinate *c, long latency) { for (int i =3D 0; i < ACCESS_COORDINATE_MAX; i++) { diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index e50dc716d4e8..b086ae88b5bb 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -39,6 +39,7 @@ static nodemask_t nodemask_region_seen =3D NODE_MASK_NONE; =20 static struct cxl_region *to_cxl_region(struct device *dev); +static void remove_devm_actions_work(struct work_struct *work); =20 #define __ACCESS_ATTR_RO(_level, _name) { \ .attr =3D { .name =3D __stringify(_name), .mode =3D 0444 }, \ @@ -2589,6 +2590,8 @@ static struct cxl_region *cxl_region_alloc(struct cxl= _root_decoder *cxlrd, int i dev->type =3D &cxl_region_type; cxl_region_setup_flags(cxlr, &cxlrd->cxlsd.cxld); =20 + INIT_WORK(&cxlr->remove_work, remove_devm_actions_work); + return cxlr; } =20 @@ -2831,6 +2834,30 @@ cxl_find_region_by_name(struct cxl_root_decoder *cxl= rd, const char *name) return to_cxl_region(region_dev); } =20 +static bool remove_devm_actions(struct cxl_region *cxlr) +{ + return schedule_cxl_region_remove_devm_actions(cxlr); +} + +static void remove_devm_actions_work(struct work_struct *work) +{ + struct cxl_region *cxlr =3D container_of(work, typeof(*cxlr), remove_work= ); + struct cxl_root_decoder *cxlrd =3D cxlr->cxlrd; + struct cxl_port *port =3D to_cxl_port(cxlrd->cxlsd.cxld.dev.parent); + + if (test_and_set_bit(CXL_REGION_F_DEVM_REMOVE, &cxlr->flags)) { + put_device(&cxlr->dev); + return; + } + + scoped_guard(device, port->uport_dev) { + if (port->uport_dev->driver) + devm_remove_action(port->uport_dev, unregister_region, cxlr); + } + + put_device(&cxlr->dev); +} + static ssize_t delete_region_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 1297594beaec..31ca4e6676ed 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -447,6 +447,12 @@ struct cxl_region_params { */ #define CXL_REGION_F_NORMALIZED_ADDRESSING 3 =20 +/* Indicate that this region is being unregistered to prevent a race. */ +#define CXL_REGION_F_UNREGISTER 4 + +/* Indicate that this region called devm_remove_action. */ +#define CXL_REGION_F_DEVM_REMOVE 5 + /** * struct cxl_region - CXL region * @dev: This region's device @@ -462,6 +468,7 @@ struct cxl_region_params { * @coord: QoS access coordinates for the region * @node_notifier: notifier for setting the access coordinates to node * @adist_notifier: notifier for calculating the abstract distance of node + * @remove_work: trigger the remove action in a safe context to acquire lo= cks */ struct cxl_region { struct device dev; @@ -477,6 +484,7 @@ struct cxl_region { struct access_coordinate coord[ACCESS_COORDINATE_MAX]; struct notifier_block node_notifier; struct notifier_block adist_notifier; + struct work_struct remove_work; }; =20 struct cxl_nvdimm_bridge { @@ -733,6 +741,7 @@ struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev, struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd, struct cxl_dport **dport); bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd); +bool schedule_cxl_region_remove_devm_actions(struct cxl_region *cxlr); =20 struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port, struct device *dport, int port_id, --=20 2.47.3 From nobody Wed Jun 17 07:35:34 2026 Received: from mail-yx1-f50.google.com (mail-yx1-f50.google.com [74.125.224.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7765435B645 for ; Mon, 27 Apr 2026 03:26:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777260393; cv=none; b=ZyYnlCfxUJ0cbD7kRZJNTCmGp9dfYRENRdEp3jYvcpV7DdPky79YffHq6bpy6tEv5BNhlHe3P8NlIm58GOIsNTW8gGcIO/gGrWc50nsY8njAdq2/0Kk5Ku6F81NSFRmF0ZgZnapGgqlXEAa4E5fEgPKugn5mvOsUQPxunVs/ImE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777260393; c=relaxed/simple; bh=/tuIm7lBZ2ovM2HT2MHU2C5GZd5ttgZkhMqpDfT31H0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cQMcJ5tn72flxrFlXbgf2VRQvbKCmoDGu3vBgw1A9FlToZrjQkI1Tp4Qgy+UaYdAYqh+LzkBxuDhQGlBm0VkSiFi2eq6JmdhdGu1PCnCbaEktBD1U0G1cDeS9AdDPg2xi0gRWe35XO1IUAtDc0jh45D+ev3FwTZYUZL210J2h5U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=sung-woo.kim; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=74.125.224.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=sung-woo.kim Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-yx1-f50.google.com with SMTP id 956f58d0204a3-651c7ddf514so8448206d50.1 for ; Sun, 26 Apr 2026 20:26:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777260391; x=1777865191; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=jL0w3++j1T4lvfmJHedjOyHD2Gu9RdXz+BDQhF932Xw=; b=Un4FpEJTHLyB5N6cQoeO936FhegNigNSxcKRAXtxuAZuqflsfl9MfVGCcKIL3HVtFt adpnAykuOLrXj+p3icS79uFetVfhS9qwQE/pYfQjCJ3Fz6eTj8Qq3jVeccMugv6PThSV aO3keAalIndOaN8OgpYkTwc0LpttJ949dvj1pMuDYgSj8lh/cV+Zx5MisbhhIraKGgb6 xhPuWUb9TaEiKimXYB930RZrvJFycu4lHtxopm0Dl1O8vptmOiXwGiwY9SZNBuMKHTpw +UgWJpGnnxYqHJqdMkbV+WZpL7eWouNtrH/7uuIAEMErxW61ymC2/AL/PjlLAJxAYVdb bLzA== X-Forwarded-Encrypted: i=1; AFNElJ+JnQoJkZrtGdoR091Pv3j6SYdcMoDDh25IH/nd5bKOvxbsHhsUZP7P7QDlIsUQZeG6Bb04Ft22slntnQE=@vger.kernel.org X-Gm-Message-State: AOJu0YyMVks+ooPEs+uf4P1pQQ4/ncWPdaWQyH07o43EbQ6Z59IFHPxb tAf67YoTCdT7pQhsYhPPYKBJJByXoyt6/wVq9tO60Foj889CGmNvfayQ X-Gm-Gg: AeBDieseqbOgqq6v6J4rnL4/N4TF7fN+RnuGJ5A0bAFx5qkrcfNWCjbuhHEE9YyVZSM ZcPMEHX4vxa01z+tlo/u/clzNUJ6gRWiCWrSyvdosnXn7tDeBjU4u/v3VBub9RD5zAADuw7pRyz /O0OVY6p8JMGwumh1NRrbQr/uJmvgu17Fi1d8dQWeVldvHF8bk5d1y2fl2UCo2/hRjN/9V6aE2y EkkEWwDW5RYwYAXfQdkOkbt7W8TjpvcWmGaB2r+zh1ZWTUvNzL9M9zkJKCJT0wchqRnEu9wAdbG rLrM16rJ6chs3MmyPF6igXve3j22bfpaiDsmAhKqge5Ca927chAk6Bhu4Gxw2XSUxfC7wWfIQnh KHSKPmKQOSKyFKnmmoGV1oQawMNg51+SD8BOiCETkBwUKY3ZCOCUQbGbZ4IhcGm45AOU7oBf2pT q26p7lYq0JPeemh04hV89U X-Received: by 2002:a05:690e:144c:b0:654:6cd0:f96b with SMTP id 956f58d0204a3-6546cd144b3mr13884636d50.5.1777260391520; Sun, 26 Apr 2026 20:26:31 -0700 (PDT) Received: from tofu.. ([128.210.0.165]) by smtp.googlemail.com with ESMTPSA id 956f58d0204a3-65314b26b56sm14087239d50.4.2026.04.26.20.26.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Apr 2026 20:26:31 -0700 (PDT) From: Sungwoo Kim To: Davidlohr Bueso , Jonathan Cameron , Dave Jiang , Alison Schofield , Vishal Verma , Ira Weiny , Dan Williams , Ben Widawsky Cc: Dave Tian , Sungwoo Kim , Jonathan Cameron , linux-cxl@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/2] cxl/region: Fix a race bug in delete_region_store() Date: Sun, 26 Apr 2026 23:20:10 -0400 Message-ID: <20260427032010.916681-5-iam@sung-woo.kim> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260427032010.916681-2-iam@sung-woo.kim> References: <20260427032010.916681-2-iam@sung-woo.kim> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch fixes race conditions in cxl region unregistration by (1) using remove_devm_actions() instead of directly calling devm_release_action() and (2) making unregister_region() idempotent. Race: CPU 0 CPU 1 =3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D delete_region_store() cxlr =3D cxl_find_region_by_name() delete_region_store() cxlr =3D cxl_find_region_by_name() devm_release_action() devm_release_action() // cannot find the action, WARN_ON() Splat: WARNING: drivers/base/devres.c:824 at devm_release_action drivers/base/devr= es.c:824 [inline], CPU#0: syz.1.12224/47589 WARNING: drivers/base/devres.c:824 at devm_release_action+0x2b2/0x360 drive= rs/base/devres.c:817, CPU#0: syz.1.12224/47589 It's found by a fuzzer based on Syzkaller that rapidly executes CXL's sysfs interface with QEMU CXL devices cxl-type3 and pxb-cxl. Syzkaller's CXL grammar is available at: https://github.com/swkim101/syz-cxl/blob/main/cxl.txt The bug's impact seems low, since the region has already been released. So, it does not affect users, except for a negligible warning message. Fixes: 779dd20cfb56 ("cxl/region: Add region creation support") Suggested-by: Dan Williams Signed-off-by: Sungwoo Kim Reviewed-by: Jonathan Cameron --- drivers/cxl/core/region.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index b086ae88b5bb..08b93b14a2c7 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -2544,6 +2544,9 @@ static void unregister_region(void *_cxlr) struct cxl_region_params *p =3D &cxlr->params; int i; =20 + if (test_and_set_bit(CXL_REGION_F_UNREGISTER, &cxlr->flags)) + return; + device_del(&cxlr->dev); =20 /* @@ -2863,15 +2866,18 @@ static ssize_t delete_region_store(struct device *d= ev, const char *buf, size_t len) { struct cxl_root_decoder *cxlrd =3D to_cxl_root_decoder(dev); - struct cxl_port *port =3D to_cxl_port(dev->parent); struct cxl_region *cxlr; =20 + /* remove_devm_actions_work() will put cxlr->dev. */ cxlr =3D cxl_find_region_by_name(cxlrd, buf); if (IS_ERR(cxlr)) return PTR_ERR(cxlr); =20 - devm_release_action(port->uport_dev, unregister_region, cxlr); - put_device(&cxlr->dev); + unregister_region(cxlr); + if (!remove_devm_actions(cxlr)) { + put_device(&cxlr->dev); + return -EBUSY; + } =20 return len; } @@ -3736,7 +3742,6 @@ static struct cxl_region *construct_region(struct cxl= _root_decoder *cxlrd, { struct cxl_endpoint_decoder *cxled =3D ctx->cxled; struct cxl_memdev *cxlmd =3D cxled_to_memdev(cxled); - struct cxl_port *port =3D cxlrd_to_port(cxlrd); struct cxl_dev_state *cxlds =3D cxlmd->cxlds; int rc, part =3D READ_ONCE(cxled->part); struct cxl_region *cxlr; @@ -3757,7 +3762,12 @@ static struct cxl_region *construct_region(struct cx= l_root_decoder *cxlrd, =20 rc =3D __construct_region(cxlr, ctx); if (rc) { - devm_release_action(port->uport_dev, unregister_region, cxlr); + /* remove_devm_actions_work() will put the device */ + get_device(&cxlr->dev); + unregister_region(cxlr); + if (!remove_devm_actions(cxlr)) + put_device(&cxlr->dev); + return ERR_PTR(rc); } =20 --=20 2.47.3