From nobody Sat Sep 26 04:30:04 2026 Received: from mail-pj1-f72.google.com (mail-pj1-f72.google.com [209.85.216.72]) (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 4627C492183 for ; Fri, 4 Sep 2026 15:53:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788537194; cv=none; b=MlrGgLf1peyhw95ucu4oekkKEk21MaNwwSPJNbkVnDUfQ8aHmbaJJHCpH4tm5357rBAtw18uyhR7EAVyVhXhfmj241HLX9nyGQc62oRQtsEeeDzk8Mw9W/ukPPRKnPvGP0NpDs2fujijzuIdb2gr5N0mEqYzB5EC89RMTn/nzPQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788537194; c=relaxed/simple; bh=5KUfU2UUZ3fPmA3o93xPIyFBexPShXAE5Elg3/MLXI0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ICrSIi9tGvvOc1YHtFyQ7W9fpcZNhRVFDCFuRH1HTtWurSdAByQb9oNAC1Ayxmxe3vKg7TvpDdgq6+ZgRxGD03W38UyUTPjJMPh2zy+QYUDwjcfMl5EjUZEWN+3DUlb8Uf2FedpZd/TX/BZ32ZQMEqEooeISoY1d1BEwh8Zxf88= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=sYtt3Jjq; arc=none smtp.client-ip=209.85.216.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="sYtt3Jjq" Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-39aee9b4cf2so1752434a91.0 for ; Fri, 04 Sep 2026 08:53:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1788537191; x=1789141991; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Pt0L+O53/xVVWaghU8W5mtgRgEzuJWx3ygItaBNaDoI=; b=sYtt3JjqgqrxjTUwTKQ48SeOu1rBtDHyIAbMrvXveHPkKuNpA3//lElGk+n0WPdbmN Ct5/HJvfeVut+QoL0/DczRMkTfS5Ib9+z9MV92pvLoPn0bWk/nBuUnobPzaaiM6CMhKN +uWnkGJ7jilK4cQFHTfeWj4pD+sXHNCLYHAyh/DqeeHy9GaKU5xcKR3rmwytb98GK6DH o+0aUaIinDWCoFnuQs9lOguBa2FyH8jKvRwGTDvckFMBMVEQqoNYM3sfOlAxuXmtkfmb Jdg+ln/ecJ8bfQo4KA7dpy+F3Q0yJEPDkVOcVG14CmffzH92lLvVgQx+CFc2FhjlD32d wMwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788537191; x=1789141991; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Pt0L+O53/xVVWaghU8W5mtgRgEzuJWx3ygItaBNaDoI=; b=SZqjf2c1tro3LflKY14HSflSad5fkbbi3/HlIIvx0H4B4TsOZMOwBycp30GAPxajYq InHf0TFH1tHwwZ+3REolzju1Mj/5oXbE1QnSpsBSUF6cEOOEEhoifmsoA04vpaYg6J3T 9tXdEtxgS9xS0hSOz4/J2xv+0TNiq/ehG3VyZSGo+VHqUZx84DlKqXu8JCmXF1nrqcPk uspuy1UQm4Jt33031+074tCatL4zoc6yQ3s0gW3oXwGYnxfg6vE4nSedrIdZQBYnJP3l eN5zRvrJ2861eBxqXLGwTChUVyH2u/GHtJ8H6Khtn/RewCgbrhcReRHdu9FfKSsLH7dQ VRSw== X-Forwarded-Encrypted: i=1; AKwUvBwZYBDCdCDuAFs0XBD1lH0kyrjn1YgWpSl0CAfPQhpPzxO/KpIFVhQczW9WLiFgLo1JKdBmwQKEgA6t7Ck=@vger.kernel.org X-Gm-Message-State: AFuF++lcVRnUl3CaK43JVxzPs+1x67SPohniiZiZR9cRK9mPx5VDitwA eCi4PxvKSnX2+Rl7XxvCbZQB0//1xkQY40OpqhzUlrWEJ8vD1CWXpREy51QzE+mU38jbgGSW/0E o/+ucow6fiXLSdcvvu1JCNA== X-Received: from pjyp14.prod.google.com ([2002:a17:90a:e70e:b0:395:1a86:4fe8]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90a:e7ce:b0:398:bacb:1137 with SMTP id 98e67ed59e1d1-39b2624a1bbmr9099604a91.19.1788537191083; Fri, 04 Sep 2026 08:53:11 -0700 (PDT) Date: Fri, 4 Sep 2026 23:53:05 +0800 In-Reply-To: <20260904155307.150443-1-stanleyjhu@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260904155307.150443-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.55.0.979.g7e5102b832-goog Message-ID: <20260904155307.150443-2-stanleyjhu@google.com> Subject: [PATCH v2 1/3] rpmb: core: Pin parent device and guard requests with rwsem From: Stanley Jhu To: Jens Wiklander , "Martin K . Petersen" , linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Bart Van Assche , Brian Kao , Brian Kao , Avri Altman , Greg Kroah-Hartman , "James E . J . Bottomley" , Stanley Jhu , stable@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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) subsys= tem") Signed-off-by: Stanley Jhu 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 relea= se. - 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; =20 - 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 =3D 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); =20 @@ -62,6 +72,7 @@ static void rpmb_dev_release(struct device *dev) { struct rpmb_dev *rdev =3D to_rpmb_dev(dev); =20 + 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; =20 + down_write(&rdev->lock); + rdev->dead =3D true; + up_write(&rdev->lock); + device_del(&rdev->dev); =20 rpmb_dev_put(rdev); @@ -164,6 +179,7 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev, rdev =3D kzalloc_obj(*rdev); if (!rdev) return ERR_PTR(-ENOMEM); + init_rwsem(&rdev->lock); rdev->descr =3D *descr; rdev->descr.dev_id =3D kmemdup(descr->dev_id, descr->dev_id_len, GFP_KERNEL); @@ -179,7 +195,7 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev, =20 dev_set_name(&rdev->dev, "rpmb%d", rdev->id); rdev->dev.class =3D &rpmb_class; - rdev->dev.parent =3D dev; + rdev->dev.parent =3D get_device(dev); =20 ret =3D 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__ =20 #include +#include #include =20 /** @@ -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; }; =20 #define to_rpmb_dev(x) container_of((x), struct rpmb_dev, dev) --=20 2.55.0.979.g7e5102b832-goog From nobody Sat Sep 26 04:30:04 2026 Received: from mail-pl1-f199.google.com (mail-pl1-f199.google.com [209.85.214.199]) (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 D817D4D8DAB for ; Fri, 4 Sep 2026 15:53:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.199 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788537196; cv=none; b=eFxgQsAB2AfDQjAj3S/plCHT3te+34LX5cIQA373NjHE/QczijQMWTMzsJD+Zxd3Zd4+PKetPakzJ7HlCAJsOtHppFLnTKRPbeawbwAGl57CabPIWjK7xiZ9Z6WnUTtiVSI6nXDQkxJWjaYoFQh4jUrNCsyWrSesXdzrDZbFQsI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788537196; c=relaxed/simple; bh=KxQ/xT0DYKwU2LbKreDOy6TYIoy1TjmaHvLHDuiy/ao=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=dOrTSAkKpt19wo5zJ3sSkQcKUhI+l8zIzWsqN+TBVni9LXGWuUO9sMGMO+mocBqKj0u3DiJvfBOP5Lqs6YxxbEf85h0jic2rxW2c9BB8y5y7om+nb9aSUKqBmtXHuBG9cI1KjQmljcnmBK0AiD6kbUhlVCDtbjZpXXjSxMibgjk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=VMWwSU7x; arc=none smtp.client-ip=209.85.214.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="VMWwSU7x" Received: by mail-pl1-f199.google.com with SMTP id d9443c01a7336-2d6f73d0f89so14337085ad.0 for ; Fri, 04 Sep 2026 08:53:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1788537193; x=1789141993; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=SZ/ecOPIdjxmv5yFmcmarX+CSOgmUYOSBiePLwGv5ws=; b=VMWwSU7xVGiRi7C1I/vkKM3X8P9Bc060yjvJ77mUpEMDVJSTxXvLsnXP35R4MfILNz T9jgXgBJEAajFd+e6UsKv90dTtxlaWNGjNiIznYlTQy4LMyYqrMch9R8FQB6tnwV3lZG qqYx2KKJrEucHhIToN0UrRD+KuLo+adBFdsJiQIDkY149dcoVXa8XQ9wmrkuYvWMGLEx bfsg1RKd6WYR6olasmAxXplKcrXaiUVDPZFabqm3bKT5jhdy5SRmK7RZiQyErJ3pwp/f pg84d/yfNBVlXdOq4SW6WEOMZWxQNs2vuCptEJdn4JNxHWFp4EBxyAGe9MDrnTdVReHK FAUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788537193; x=1789141993; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=SZ/ecOPIdjxmv5yFmcmarX+CSOgmUYOSBiePLwGv5ws=; b=dEktHEF91o40g/cZ4whyfn+6b3/5xzMabChS+IGHTR4gM/8HVgQ6ruhDI83/sAbWen EvrNNKubbCuKTT0IutrA93nK2e8bW4JI/obyj18OJzSS7PlHgvsbb/UkziyEW1L7zMVg gkZHDu/zQjxAeLWilmAENmdq+p4PgGSQ4nqlTkksghKgezHresyILcQ7uTyHYp17MmZC sdiSBdyBKX6pfgJYIFxhKaV9vxTheXK9ZlSccl8+4r4e0iEKnklE3YRMvObgNx5UlH0n 1ZxKGsyyjZ+acH4aO4jMo3QxG9g6xsxvTyhJuokyD4kar8MqjWgSUlptN+ng8DZi4iBU IbwQ== X-Forwarded-Encrypted: i=1; AKwUvByrI0ylLOZdSNCl+Jeiu54TVFQm9StD3V6SU+gUWBqgGrVHl3GtDuJwwnsjhSC/9WZ0SSqyHMQTVMj0lMg=@vger.kernel.org X-Gm-Message-State: AFuF++kXMAsjZISvTASzEF6kTuUe47CSsekUkICwxpJCLXC8uHEAFvwA z94ejutCyxPJVQcWxaq/b5ON87NwllJO4fD2qyFTEqHs+MMwkLcMvITQWHTgGqF/G3ioqCRsT8p +xygnf+bXruTAeoSN/SFLxw== X-Received: from pjbmd22.prod.google.com ([2002:a17:90b:23d6:b0:38e:6cdf:217a]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4fca:b0:38e:5b59:c2ff with SMTP id 98e67ed59e1d1-39b260dd278mr10377291a91.3.1788537193245; Fri, 04 Sep 2026 08:53:13 -0700 (PDT) Date: Fri, 4 Sep 2026 23:53:06 +0800 In-Reply-To: <20260904155307.150443-1-stanleyjhu@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260904155307.150443-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.55.0.979.g7e5102b832-goog Message-ID: <20260904155307.150443-3-stanleyjhu@google.com> Subject: [PATCH v2 2/3] scsi: ufs: rpmb: Decouple device lifecycle from devres to avoid UAF From: Stanley Jhu To: Jens Wiklander , "Martin K . Petersen" , linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Bart Van Assche , Brian Kao , Brian Kao , Avri Altman , Greg Kroah-Hartman , "James E . J . Bottomley" , Stanley Jhu , stable@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" struct ufs_rpmb_dev embeds struct device, but is allocated using devm_kzalloc() tied to the host controller (hba->dev). When the host controller unbinds, devres automatically frees ufs_rpmb regardless of active references to ufs_rpmb->dev (such as sysfs users or child devices). Subsequent access to ufs_rpmb->dev triggers a Use-After-Free (UAF) kernel Oops. Fix this by decoupling ufs_rpmb from devres, managing its lifetime strictly through the embedded device reference count, and pinning the underlying SCSI device. Fixes: b06b8c421485 ("scsi: ufs: core: Add OP-TEE based RPMB driver for UFS= devices") Signed-off-by: Stanley Jhu Cc: stable@vger.kernel.org --- Changes in v2: - Explicitly unregister rpmb device before unregistering ufs_rpmb dev. drivers/ufs/core/ufs-rpmb.c | 86 +++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/drivers/ufs/core/ufs-rpmb.c b/drivers/ufs/core/ufs-rpmb.c index aa925cbb07e8..fe96acdde278 100644 --- a/drivers/ufs/core/ufs-rpmb.c +++ b/drivers/ufs/core/ufs-rpmb.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -33,15 +34,19 @@ struct ufs_rpmb_dev { u8 region_id; struct device dev; struct rpmb_dev *rdev; - struct ufs_hba *hba; + struct scsi_device *sdev; struct list_head node; }; =20 -static int ufs_sec_submit(struct ufs_hba *hba, u16 spsp, void *buffer, siz= e_t len, bool send) +static int ufs_sec_submit(struct ufs_rpmb_dev *ufs_rpmb, u16 spsp, + void *buffer, size_t len, bool send) { - struct scsi_device *sdev =3D hba->ufs_rpmb_wlun; + struct scsi_device *sdev =3D ufs_rpmb->sdev; u8 cdb[12] =3D { }; =20 + if (!sdev || !scsi_device_online(sdev)) + return -ENODEV; + cdb[0] =3D send ? SECURITY_PROTOCOL_OUT : SECURITY_PROTOCOL_IN; cdb[1] =3D UFS_RPMB_SEC_PROTOCOL; put_unaligned_be16(spsp, &cdb[2]); @@ -53,13 +58,12 @@ static int ufs_sec_submit(struct ufs_hba *hba, u16 spsp= , void *buffer, size_t le =20 /* UFS RPMB route frames implementation */ static int ufs_rpmb_route_frames(struct device *dev, u8 *req, unsigned int= req_len, u8 *resp, - unsigned int resp_len) + unsigned int resp_len) { struct ufs_rpmb_dev *ufs_rpmb =3D dev_get_drvdata(dev); struct rpmb_frame *frm_out =3D (struct rpmb_frame *)req; bool need_result_read =3D true; u16 req_type, protocol_id; - struct ufs_hba *hba; int ret; =20 if (!ufs_rpmb) { @@ -67,8 +71,6 @@ static int ufs_rpmb_route_frames(struct device *dev, u8 *= req, unsigned int req_l return -ENODEV; } =20 - hba =3D ufs_rpmb->hba; - /* req_resp is at the end of an RPMB frame. */ if (req_len < sizeof(*frm_out)) return -EINVAL; @@ -101,7 +103,7 @@ static int ufs_rpmb_route_frames(struct device *dev, u8= *req, unsigned int req_l =20 protocol_id =3D ufs_rpmb->region_id << 8 | UFS_RPMB_SEC_PROTOCOL_ID; =20 - ret =3D ufs_sec_submit(hba, protocol_id, req, req_len, true); + ret =3D ufs_sec_submit(ufs_rpmb, protocol_id, req, req_len, true); if (ret) { dev_err(dev, "Command failed with ret=3D%d\n", ret); return ret; @@ -112,7 +114,7 @@ static int ufs_rpmb_route_frames(struct device *dev, u8= *req, unsigned int req_l =20 memset(frm_resp, 0, sizeof(*frm_resp)); put_unaligned_be16(RPMB_RESULT_READ, &frm_resp->req_resp); - ret =3D ufs_sec_submit(hba, protocol_id, resp, resp_len, true); + ret =3D ufs_sec_submit(ufs_rpmb, protocol_id, resp, resp_len, true); if (ret) { dev_err(dev, "Result read request failed with ret=3D%d\n", ret); return ret; @@ -120,7 +122,7 @@ static int ufs_rpmb_route_frames(struct device *dev, u8= *req, unsigned int req_l } =20 if (!ret) { - ret =3D ufs_sec_submit(hba, protocol_id, resp, resp_len, false); + ret =3D ufs_sec_submit(ufs_rpmb, protocol_id, resp, resp_len, false); if (ret) dev_err(dev, "Response read failed with ret=3D%d\n", ret); } @@ -130,22 +132,24 @@ static int ufs_rpmb_route_frames(struct device *dev, = u8 *req, unsigned int req_l =20 static void ufs_rpmb_device_release(struct device *dev) { - struct ufs_rpmb_dev *ufs_rpmb =3D dev_get_drvdata(dev); + struct ufs_rpmb_dev *ufs_rpmb =3D container_of(dev, struct ufs_rpmb_dev, = dev); =20 - rpmb_dev_unregister(ufs_rpmb->rdev); + scsi_device_put(ufs_rpmb->sdev); + kfree(ufs_rpmb); } =20 /* UFS RPMB device registration */ int ufs_rpmb_probe(struct ufs_hba *hba) { + struct scsi_device *sdev =3D hba->ufs_rpmb_wlun; struct ufs_rpmb_dev *ufs_rpmb, *it, *tmp; struct rpmb_dev *rdev; - char *cid =3D NULL; + char *cid; int region; u32 cap; int ret; =20 - if (!hba->ufs_rpmb_wlun || hba->dev_info.b_advanced_rpmb_en) { + if (!sdev || hba->dev_info.b_advanced_rpmb_en) { dev_info(hba->dev, "Skip OP-TEE RPMB registration\n"); return -ENODEV; } @@ -167,14 +171,23 @@ int ufs_rpmb_probe(struct ufs_hba *hba) if (!cap) continue; =20 - ufs_rpmb =3D devm_kzalloc(hba->dev, sizeof(*ufs_rpmb), GFP_KERNEL); + ufs_rpmb =3D kzalloc_obj(*ufs_rpmb); if (!ufs_rpmb) { ret =3D -ENOMEM; goto err_out; } =20 - ufs_rpmb->hba =3D hba; - ufs_rpmb->dev.parent =3D &hba->ufs_rpmb_wlun->sdev_gendev; + INIT_LIST_HEAD(&ufs_rpmb->node); + + ret =3D scsi_device_get(sdev); + if (ret) { + kfree(ufs_rpmb); + goto err_out; + } + + ufs_rpmb->sdev =3D sdev; + ufs_rpmb->region_id =3D region; + ufs_rpmb->dev.parent =3D &sdev->sdev_gendev; ufs_rpmb->dev.bus =3D &ufs_rpmb_bus_type; ufs_rpmb->dev.release =3D ufs_rpmb_device_release; dev_set_name(&ufs_rpmb->dev, "ufs_rpmb%d", region); @@ -185,16 +198,14 @@ int ufs_rpmb_probe(struct ufs_hba *hba) ret =3D device_register(&ufs_rpmb->dev); if (ret) { dev_err(hba->dev, "Failed to register UFS RPMB device %d\n", region); - put_device(&ufs_rpmb->dev); - goto err_out; + goto err_put; } =20 /* Create unique ID by appending region number to device_id */ cid =3D kasprintf(GFP_KERNEL, "%s-R%d", hba->dev_info.device_id, region); if (!cid) { - device_unregister(&ufs_rpmb->dev); ret =3D -ENOMEM; - goto err_out; + goto err_unreg; } =20 descr.dev_id =3D cid; @@ -203,29 +214,33 @@ int ufs_rpmb_probe(struct ufs_hba *hba) =20 /* Register RPMB device */ rdev =3D rpmb_dev_register(&ufs_rpmb->dev, &descr); + kfree(cid); if (IS_ERR(rdev)) { dev_err(hba->dev, "Failed to register UFS RPMB device.\n"); - device_unregister(&ufs_rpmb->dev); ret =3D PTR_ERR(rdev); - goto err_out; + goto err_unreg; } =20 - kfree(cid); - cid =3D NULL; - ufs_rpmb->rdev =3D rdev; - ufs_rpmb->region_id =3D region; - list_add_tail(&ufs_rpmb->node, &hba->rpmbs); =20 dev_info(hba->dev, "UFS RPMB region %d registered (capacity=3D%u)\n", re= gion, cap); } =20 return 0; + +err_unreg: + device_unregister(&ufs_rpmb->dev); + goto err_out; +err_put: + put_device(&ufs_rpmb->dev); err_out: - kfree(cid); list_for_each_entry_safe(it, tmp, &hba->rpmbs, node) { - list_del(&it->node); + list_del_init(&it->node); + if (it->rdev) { + rpmb_dev_unregister(it->rdev); + it->rdev =3D NULL; + } device_unregister(&it->dev); } =20 @@ -242,14 +257,13 @@ void ufs_rpmb_remove(struct ufs_hba *hba) =20 /* Remove all registered RPMB devices */ list_for_each_entry_safe(ufs_rpmb, tmp, &hba->rpmbs, node) { - dev_info(hba->dev, "Removing UFS RPMB region %d\n", ufs_rpmb->region_id); - /* Remove from list first */ - list_del(&ufs_rpmb->node); - /* Unregister device */ + list_del_init(&ufs_rpmb->node); + if (ufs_rpmb->rdev) { + rpmb_dev_unregister(ufs_rpmb->rdev); + ufs_rpmb->rdev =3D NULL; + } device_unregister(&ufs_rpmb->dev); } - - dev_info(hba->dev, "All UFS RPMB devices unregistered\n"); } =20 MODULE_LICENSE("GPL v2"); --=20 2.55.0.979.g7e5102b832-goog From nobody Sat Sep 26 04:30:04 2026 Received: from mail-pj1-f72.google.com (mail-pj1-f72.google.com [209.85.216.72]) (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 4FE4848BD57 for ; Fri, 4 Sep 2026 15:53:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788537198; cv=none; b=V2BsNXKlRX2WrD3m34NRGamXmrlDErzcUqFGnoqM/o766O9ZGySuKX0zYO7qdxtq6EXGzigAGX561i801rXIqHgsXOoy6kGcfLT7W7MSKxarIgpUfEWJUrzCn7ItMJy0P+k47Ew6bRfLgFVyRFjiRBplK7CmePN7l6h9xwI9WDA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788537198; c=relaxed/simple; bh=s4vt5UQI92yBZEhWRd1KakBiy4b51SnXf54Q6GDpQUc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=FWLUmPao0MdZXJMROnXFAwLMrKYZDXFocT6MRH9ePjxWa8c4Ag6TkoPYlytDBtdIFw4bZsH5ji1mH9rnpeZE4i9KnxTb3c64JaHWZBrqad+0DKg1k1iG76+YDmHHn1poiWnitZhkA1Ikg3tsOMS1DiEMNJA6DTNBBp2sVf8cexA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=TTHUkr5p; arc=none smtp.client-ip=209.85.216.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="TTHUkr5p" Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-39906175917so1332143a91.2 for ; Fri, 04 Sep 2026 08:53:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1788537195; x=1789141995; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=CAwO2E8HU/J4mifuSn0aiL69IdIeEkkIoQgO6TpMlRc=; b=TTHUkr5pGZBsqzukf5MMpb2iW9SSu5Rl4PV07QXj+GEk5u5ZHtbMHENEZJrBi4gFqb p08jh7tLViP6WobhvOYTcJHjJ0gEJclfOidaxahZ+8o0Np0eju/LfDIbuKiMV6wOejqG wsZ7Fn5StIopFhvVJEsS7g3J9T2gllRyXClGtOdAFIInKWiZUsQU8jIejh5WUvkNg3WZ UL53RNxmo+E51J6+I6Nhe5sq1mIUxSsedTYBkhCsao3QXgWpnH1XrODeTQMKZ+IUv+sA P7tTEXVpMIT/hwVI+wTdYjBhd8JzyWc1uIk9K3Wi+EBcXF3b/qNr69LcoT5t+2Rj+qpq HEww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788537195; x=1789141995; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=CAwO2E8HU/J4mifuSn0aiL69IdIeEkkIoQgO6TpMlRc=; b=DKl5Nec9Rm44ZBxm2K+7Xo8mpcxYigDmWvu+qvsNbLw+TmiDwLz4xtxc6kv9lUJE6w EBhmCJo0Vqa2BYUF0tCGp3cVz6/7/ISmUqvPMAxr7NKqBr9BzeAWhZUTRg4Te+SNcj31 W/GiUGjILpHqw1L6lkapBGIiLY0gVEeN0nWe9W/bh6uDh5iFOL8QGl5YYUml6CPSCUw0 2BMlyHCS6F//euwYo0wvURLK6tAqmaZXz6IMuSiZyDdNp+yv8U8QVy5dPaGz6gGmqJYX YtMomixEwRUZnj+lIibVvbhrgthIE+Q7/RvrQbhbj3GHhbPH3taHqSLCXb4xQ6Nt8QZO jnQg== X-Forwarded-Encrypted: i=1; AKwUvBy27em3Boa3jUJIG0p2VWl+j4pvFlDaZVPXQuLxp6/HgJF5SWVQoPPv1BAt08AXiKl6pxTTxn9DhCgDunQ=@vger.kernel.org X-Gm-Message-State: AFuF++l+r5VpoMUG8x4DJ8Wyp+TzczRdZOv6LYeNaQFsWhS2qeP2Mxr5 0N8S8IrWkldHZCeKDTt046rdye3PHTunm+T2Yr18/T8VdRHec2Yf74bRJDUZQpWirFBoUhIEgxn dDpisRII7JM0zr0cb0dZImg== X-Received: from pjbmy11.prod.google.com ([2002:a17:90b:4c8b:b0:396:5b40:4ebb]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4cce:b0:38f:240d:b857 with SMTP id 98e67ed59e1d1-39b260dd4e9mr11206681a91.2.1788537195308; Fri, 04 Sep 2026 08:53:15 -0700 (PDT) Date: Fri, 4 Sep 2026 23:53:07 +0800 In-Reply-To: <20260904155307.150443-1-stanleyjhu@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260904155307.150443-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.55.0.979.g7e5102b832-goog Message-ID: <20260904155307.150443-4-stanleyjhu@google.com> Subject: [PATCH v2 3/3] scsi: ufs: rpmb: Register and unregister ufs_rpmb_bus_type From: Stanley Jhu To: Jens Wiklander , "Martin K . Petersen" , linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Bart Van Assche , Brian Kao , Brian Kao , Avri Altman , Greg Kroah-Hartman , "James E . J . Bottomley" , Stanley Jhu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The UFS RPMB driver defines ufs_rpmb_bus_type and assigns it to the bus member of struct device for each RPMB device. However, ufs_rpmb_bus_type is never registered with the driver core via bus_register(). When driver core rejects devices assigned to unregistered buses with -EINVAL in bus_add_device(), device_register(&ufs_rpmb->dev) in ufs_rpmb_probe() fails with: "bus_add_device: cannot add device 'ufs_rpmb0' to unregistered bus 'ufs_rpmb'" "ufshcd: Failed to register UFS RPMB device 0" Fix this by registering ufs_rpmb_bus_type in ufshcd_core_init() and unregistering it in ufshcd_core_exit(). Fixes: b06b8c421485 ("scsi: ufs: core: Add OP-TEE based RPMB driver for UFS= devices") Signed-off-by: Stanley Jhu --- drivers/ufs/core/ufs-rpmb.c | 10 ++++++++++ drivers/ufs/core/ufshcd-priv.h | 13 ++++++++++++- drivers/ufs/core/ufshcd.c | 16 ++++++++++++++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/ufs/core/ufs-rpmb.c b/drivers/ufs/core/ufs-rpmb.c index fe96acdde278..1889ea10d5df 100644 --- a/drivers/ufs/core/ufs-rpmb.c +++ b/drivers/ufs/core/ufs-rpmb.c @@ -29,6 +29,16 @@ static const struct bus_type ufs_rpmb_bus_type =3D { .name =3D "ufs_rpmb", }; =20 +int __init ufs_rpmb_bus_register(void) +{ + return bus_register(&ufs_rpmb_bus_type); +} + +void ufs_rpmb_bus_unregister(void) +{ + bus_unregister(&ufs_rpmb_bus_type); +} + /* UFS RPMB device structure */ struct ufs_rpmb_dev { u8 region_id; diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index e55c2a02c1f5..d5e0cc3edb5b 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -493,10 +493,21 @@ static inline u32 ufshcd_mcq_get_sq_head_slot(struct = ufs_hw_queue *q) return val / sizeof(struct utp_transfer_req_desc); } =20 -#if IS_ENABLED(CONFIG_RPMB) +#if IS_REACHABLE(CONFIG_RPMB) +int __init ufs_rpmb_bus_register(void); +void ufs_rpmb_bus_unregister(void); int ufs_rpmb_probe(struct ufs_hba *hba); void ufs_rpmb_remove(struct ufs_hba *hba); #else +static inline int ufs_rpmb_bus_register(void) +{ + return 0; +} + +static inline void ufs_rpmb_bus_unregister(void) +{ +} + static inline int ufs_rpmb_probe(struct ufs_hba *hba) { return 0; diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index a25b6a0cb5c6..4470e3d65c5c 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -11584,16 +11584,28 @@ static int __init ufshcd_core_init(void) =20 ufs_debugfs_init(); =20 + ret =3D ufs_rpmb_bus_register(); + if (ret) + goto err_debugfs; + ret =3D scsi_register_driver(&ufs_dev_wlun_template); if (ret) - ufs_debugfs_exit(); + goto err_rpmb_bus; + + return 0; + +err_rpmb_bus: + ufs_rpmb_bus_unregister(); +err_debugfs: + ufs_debugfs_exit(); return ret; } =20 static void __exit ufshcd_core_exit(void) { - ufs_debugfs_exit(); scsi_unregister_driver(&ufs_dev_wlun_template); + ufs_rpmb_bus_unregister(); + ufs_debugfs_exit(); } =20 module_init(ufshcd_core_init); --=20 2.55.0.979.g7e5102b832-goog