From: Tzung-Bi Shih <tzungbi@kernel.org>
To: Jason Gunthorpe <jgg@nvidia.com>
Cc: Benson Leung <bleung@chromium.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J . Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>,
Jonathan Corbet <corbet@lwn.net>, Shuah Khan <shuah@kernel.org>,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Bartosz Golaszewski <brgl@bgdev.pl>,
Wolfram Sang <wsa+renesas@sang-engineering.com>,
Simona Vetter <simona.vetter@ffwll.ch>,
Dan Williams <dan.j.williams@intel.com>
Subject: Re: [PATCH v5 5/7] revocable: Add fops replacement
Date: Sun, 19 Oct 2025 23:08:29 +0800 [thread overview]
Message-ID: <aPT-7TTgW_Xop99j@tzungbi-laptop> (raw)
In-Reply-To: <20251017162116.GA316284@nvidia.com>
On Fri, Oct 17, 2025 at 01:21:16PM -0300, Jason Gunthorpe wrote:
> On Sat, Oct 18, 2025 at 12:07:58AM +0800, Tzung-Bi Shih wrote:
> > > This is already properly lifetime controlled!
> > >
> > > It *HAS* to be, and even your patches are assuming it by blindly
> > > reaching into the parent's memory!
> > >
> > > + misc->rps[0] = ec->ec_dev->revocable_provider;
> > >
> > > If the parent driver has been racily unbound at this point the
> > > ec->ec_dev is already a UAF!
> >
> > Not really, it uses the fact that the caller is from probe(). I think the
> > driver can't be unbound when it is still in probe().
>
> Right, but that's my point you are already relying on driver binding
> lifetime rules to make your access valid. You should continue to rely
> on that and fix the lack of synchronous remove to fix the bug.
I think what you're looking for is something similar to the following
patches.
- Instead of having a real resource to protect with revocable, use the
subsystem device itself as a virtual resource. Revoke the virtual
resource when unregistering the device from the subsystem.
- Exit earlier if the virtual resource is NULL (i.e. the subsystem device
has been unregistered) in the file operation wrappers.
By doing so, we don't need to provide a misc_deregister_sync() which could
probably maintain a list of opening files in miscdevice and handle with all
opening files when unregistering. The device unbound is free to go and
doesn't need to wait for closing or interrupting all opening files.
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 27078541489f..bc4d249c4d0f 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -173,8 +175,12 @@ static int misc_open(struct inode *inode, struct file *file)
*/
file->private_data = c;
- err = 0;
replace_fops(file, new_fops);
+
+ err = fs_revocable_replace(c->rp, file);
+ if (err)
+ goto fail;
+
if (file->f_op->open)
err = file->f_op->open(inode, file);
fail:
@@ -234,6 +240,10 @@ int misc_register(struct miscdevice *misc)
return -EINVAL;
}
+ misc->rp = revocable_provider_alloc(misc);
+ if (!misc->rp)
+ return -ENOMEM;
+
INIT_LIST_HEAD(&misc->list);
mutex_lock(&misc_mtx);
@@ -291,6 +291,8 @@ EXPORT_SYMBOL(misc_register);
void misc_deregister(struct miscdevice *misc)
{
+ revocable_provider_revoke(misc->rp);
+
mutex_lock(&misc_mtx);
list_del_init(&misc->list);
device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor));
diff --git a/fs/fs_revocable.c b/fs/fs_revocable.c
new file mode 100644
...
+struct fs_revocable_replacement {
+ struct revocable *rev;
+ const struct file_operations *orig_fops;
+ struct file_operations fops;
+};
+
+static ssize_t fs_revocable_read(struct file *filp, char __user *buffer,
+ size_t length, loff_t *offset)
+{
+ void *any;
+ struct fs_revocable_replacement *rr = filp->f_rr;
+
+ REVOCABLE_TRY_ACCESS_WITH(rr->rev, any) {
+ if (!any)
+ return -ENODEV;
+ return rr->orig_fops->read(filp, buffer, length, offset);
+ }
+}
...
+int fs_revocable_replace(struct revocable_provider *rp, struct file *filp)
+{
+ struct fs_revocable_replacement *rr;
+
+ rr = kzalloc(sizeof(*rr), GFP_KERNEL);
+ if (!rr)
+ return -ENOMEM;
+
+ rr->rev = revocable_alloc(rp);
+ if (!rr->rev)
+ goto free_rr;
+
+ rr->orig_fops = filp->f_op;
+ memcpy(&rr->fops, filp->f_op, sizeof(rr->fops));
+ rr->fops.release = fs_revocable_release;
+
+ if (rr->fops.read)
+ rr->fops.read = fs_revocable_read;
+ if (rr->fops.poll)
+ rr->fops.poll = fs_revocable_poll;
+ if (rr->fops.unlocked_ioctl)
+ rr->fops.unlocked_ioctl = fs_revocable_unlocked_ioctl;
+
+ filp->f_rr = rr;
+ filp->f_op = &rr->fops;
+ return 0;
+free_rr:
+ kfree(rr);
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(fs_revocable_replace);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a6de8d93838d..163496a5df6c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1066,6 +1066,7 @@ struct file {
freeptr_t f_freeptr;
};
/* --- cacheline 3 boundary (192 bytes) --- */
+ struct fs_revocable_replacement *f_rr;
} __randomize_layout
__attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index aca911687bd5..c98b97f84c07 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -94,6 +94,7 @@ struct miscdevice {
const struct attribute_group **groups;
const char *nodename;
umode_t mode;
+ struct revocable_provider *rp;
};
next prev parent reply other threads:[~2025-10-19 15:08 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-16 5:41 [PATCH v5 0/7] platform/chrome: Fix a possible UAF via revocable Tzung-Bi Shih
2025-10-16 5:41 ` [PATCH v5 1/7] revocable: Revocable resource management Tzung-Bi Shih
2025-10-16 5:41 ` [PATCH v5 2/7] revocable: Add Kunit test cases Tzung-Bi Shih
2025-10-16 5:42 ` [PATCH v5 3/7] selftests: revocable: Add kselftest cases Tzung-Bi Shih
2025-10-16 5:42 ` [PATCH v5 4/7] platform/chrome: Protect cros_ec_device lifecycle with revocable Tzung-Bi Shih
2025-10-16 5:42 ` [PATCH v5 5/7] revocable: Add fops replacement Tzung-Bi Shih
2025-10-16 12:31 ` Jason Gunthorpe
2025-10-17 2:36 ` Tzung-Bi Shih
2025-10-17 13:49 ` Jason Gunthorpe
2025-10-17 16:07 ` Tzung-Bi Shih
2025-10-17 16:21 ` Jason Gunthorpe
2025-10-19 15:08 ` Tzung-Bi Shih [this message]
2025-10-20 11:57 ` Jason Gunthorpe
2025-10-21 4:49 ` Tzung-Bi Shih
2025-10-21 12:15 ` Jason Gunthorpe
2025-10-23 14:22 ` Tzung-Bi Shih
2025-10-23 14:51 ` Jason Gunthorpe
2025-10-23 15:04 ` Greg Kroah-Hartman
2025-10-23 15:57 ` Jason Gunthorpe
2025-10-23 16:20 ` Danilo Krummrich
2025-10-23 16:48 ` Jason Gunthorpe
2025-10-23 18:30 ` Danilo Krummrich
2025-12-11 3:23 ` Laurent Pinchart
2025-12-11 3:47 ` Wolfram Sang
2025-12-11 8:05 ` Laurent Pinchart
2025-12-11 8:36 ` Wolfram Sang
2025-12-11 13:43 ` Laurent Pinchart
2025-12-11 14:46 ` Tzung-Bi Shih
2025-12-12 8:32 ` Tzung-Bi Shih
2025-11-07 4:11 ` Tzung-Bi Shih
2025-11-07 14:12 ` Jason Gunthorpe
2025-10-17 16:29 ` Danilo Krummrich
2025-10-17 16:37 ` Jason Gunthorpe
2025-10-17 18:19 ` Danilo Krummrich
2025-10-17 18:44 ` Jason Gunthorpe
2025-10-17 21:41 ` Danilo Krummrich
2025-10-17 22:56 ` Jason Gunthorpe
2025-10-23 15:32 ` Danilo Krummrich
2025-10-16 18:38 ` Randy Dunlap
2025-10-17 2:41 ` Tzung-Bi Shih
2025-10-16 5:42 ` [PATCH v5 6/7] char: misc: Leverage revocable " Tzung-Bi Shih
2025-10-16 5:42 ` [PATCH v5 7/7] platform/chrome: cros_ec_chardev: Secure cros_ec_device via revocable Tzung-Bi Shih
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=aPT-7TTgW_Xop99j@tzungbi-laptop \
--to=tzungbi@kernel.org \
--cc=bleung@chromium.org \
--cc=brgl@bgdev.pl \
--cc=chrome-platform@lists.linux.dev \
--cc=corbet@lwn.net \
--cc=dakr@kernel.org \
--cc=dan.j.williams@intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=jgg@nvidia.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=rafael@kernel.org \
--cc=shuah@kernel.org \
--cc=simona.vetter@ffwll.ch \
--cc=wsa+renesas@sang-engineering.com \
/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