From: Stanley Jhu <stanleyjhu@google.com>
To: Jens Wiklander <jens.wiklander@linaro.org>,
"Martin K . Petersen" <martin.petersen@oracle.com>,
linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Bart Van Assche <bvanassche@acm.org>,
Brian Kao <brian.kao@mediatek.com>,
Brian Kao <powenkao@google.com>,
Avri Altman <avri.altman@wdc.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"James E . J . Bottomley"
<James.Bottomley@HansenPartnership.com>,
Stanley Jhu <stanleyjhu@google.com>,
stable@vger.kernel.org
Subject: [PATCH v2 1/3] rpmb: core: Pin parent device and guard requests with rwsem
Date: Fri, 4 Sep 2026 23:53:05 +0800 [thread overview]
Message-ID: <20260904155307.150443-2-stanleyjhu@google.com> (raw)
In-Reply-To: <20260904155307.150443-1-stanleyjhu@google.com>
When an RPMB device is unregistered, device_del(&rdev->dev) drops the
driver core's reference to the parent device. If external callers still
hold references to rdev, rdev outlives the parent provider (e.g. UFS
host). Once the parent is freed, subsequent access to rdev->dev.parent
causes a Use-After-Free (UAF).
Additionally, lockless access in rpmb_route_frames() races with parent
teardown, risking frame dispatch against an unpowered or torn-down host.
Fix these issues by explicitly pinning the parent device for the
lifetime of the RPMB device, and guarding in-flight requests against
device unregistration with an rw_semaphore teardown barrier.
Fixes: 1e9046e3a154 ("rpmb: add Replay Protected Memory Block (RPMB) subsystem")
Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
Cc: stable@vger.kernel.org
---
Changes in v2:
- New patch in v2 addressing cross-subsystem UAF and TOCTOU races (sashiko-bot).
- Pin parent device with get_device() in register and put_device() in release.
- Introduce rw_semaphore and dead flag to serialize in-flight requests.
drivers/misc/rpmb-core.c | 24 +++++++++++++++++-------
include/linux/rpmb.h | 5 +++++
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/misc/rpmb-core.c b/drivers/misc/rpmb-core.c
index ecf14acf230a..c0e19cfe3faa 100644
--- a/drivers/misc/rpmb-core.c
+++ b/drivers/misc/rpmb-core.c
@@ -50,11 +50,21 @@ EXPORT_SYMBOL_GPL(rpmb_dev_put);
int rpmb_route_frames(struct rpmb_dev *rdev, u8 *req,
unsigned int req_len, u8 *rsp, unsigned int rsp_len)
{
- if (!req || !req_len || !rsp || !rsp_len)
+ int ret;
+
+ if (!rdev || !req || !req_len || !rsp || !rsp_len)
return -EINVAL;
- return rdev->descr.route_frames(rdev->dev.parent, req, req_len,
- rsp, rsp_len);
+ down_read(&rdev->lock);
+ if (rdev->dead || !device_is_registered(&rdev->dev)) {
+ up_read(&rdev->lock);
+ return -ENODEV;
+ }
+
+ ret = rdev->descr.route_frames(rdev->dev.parent, req, req_len,
+ rsp, rsp_len);
+ up_read(&rdev->lock);
+ return ret;
}
EXPORT_SYMBOL_GPL(rpmb_route_frames);
@@ -62,6 +72,7 @@ static void rpmb_dev_release(struct device *dev)
{
struct rpmb_dev *rdev = to_rpmb_dev(dev);
+ put_device(rdev->dev.parent);
ida_free(&rpmb_ida, rdev->id);
kfree(rdev->descr.dev_id);
kfree(rdev);
@@ -133,6 +144,10 @@ int rpmb_dev_unregister(struct rpmb_dev *rdev)
if (!rdev)
return -EINVAL;
+ down_write(&rdev->lock);
+ rdev->dead = true;
+ up_write(&rdev->lock);
+
device_del(&rdev->dev);
rpmb_dev_put(rdev);
@@ -164,6 +179,7 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
rdev = kzalloc_obj(*rdev);
if (!rdev)
return ERR_PTR(-ENOMEM);
+ init_rwsem(&rdev->lock);
rdev->descr = *descr;
rdev->descr.dev_id = kmemdup(descr->dev_id, descr->dev_id_len,
GFP_KERNEL);
@@ -179,7 +195,7 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
dev_set_name(&rdev->dev, "rpmb%d", rdev->id);
rdev->dev.class = &rpmb_class;
- rdev->dev.parent = dev;
+ rdev->dev.parent = get_device(dev);
ret = device_register(&rdev->dev);
if (ret) {
diff --git a/include/linux/rpmb.h b/include/linux/rpmb.h
index ed3f8e431eff..2d8a41716883 100644
--- a/include/linux/rpmb.h
+++ b/include/linux/rpmb.h
@@ -7,6 +7,7 @@
#define __RPMB_H__
#include <linux/device.h>
+#include <linux/rwsem.h>
#include <linux/types.h>
/**
@@ -48,15 +49,19 @@ struct rpmb_descr {
* struct rpmb_dev - device which can support RPMB partition
*
* @dev : device
+ * @lock : protects in-flight operations against teardown
* @id : device_id
* @list_node : linked list node
* @descr : RPMB description
+ * @dead : set to true when device is unregistered
*/
struct rpmb_dev {
struct device dev;
+ struct rw_semaphore lock;
int id;
struct list_head list_node;
struct rpmb_descr descr;
+ bool dead;
};
#define to_rpmb_dev(x) container_of((x), struct rpmb_dev, dev)
--
2.55.0.979.g7e5102b832-goog
next prev parent reply other threads:[~2026-09-04 15:53 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-04 15:53 [PATCH v2 0/3] Fix RPMB cross-subsystem UAF and UFS OP-TEE RPMB lifecycle Stanley Jhu
2026-09-04 15:53 ` Stanley Jhu [this message]
2026-09-04 15:53 ` [PATCH v2 2/3] scsi: ufs: rpmb: Decouple device lifecycle from devres to avoid UAF Stanley Jhu
2026-09-04 15:53 ` [PATCH v2 3/3] scsi: ufs: rpmb: Register and unregister ufs_rpmb_bus_type Stanley Jhu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260904155307.150443-2-stanleyjhu@google.com \
--to=stanleyjhu@google.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=avri.altman@wdc.com \
--cc=brian.kao@mediatek.com \
--cc=bvanassche@acm.org \
--cc=gregkh@linuxfoundation.org \
--cc=jens.wiklander@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=powenkao@google.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox