mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: Vishal Verma <vishal.l.verma@intel.com>,
	Dave Jiang <dave.jiang@intel.com>,
	Alison Schofield <alison.schofield@intel.com>,
	nvdimm@lists.linux.dev, linux-cxl@vger.kernel.org,
	fuse-devel <fuse-devel@lists.linux.dev>,
	Carlos Maiolino <cem@kernel.org>,
	linux-xfs <linux-xfs@vger.kernel.org>,
	linux-kernel@vger.kernel.org, John Groves <John@groves.net>
Subject: Re: fs_put_dax() vs. dax_holder_notify_failure() race
Date: Wed, 30 Sep 2026 08:35:06 -0700	[thread overview]
Message-ID: <20260930153506.GR6253@frogsfrogsfrogs> (raw)
In-Reply-To: <CAJfpeguyOXGQO4Q8rSAc8GxExTJU0G2o19fxRnh_93GvAoNcRg@mail.gmail.com>

On Wed, Sep 30, 2026 at 04:29:33PM +0200, Miklos Szeredi wrote:
> During ->notify_failure() callback will dereference holder.  It may be
> NULL at this point, resulting in an Oops, or it may be non-NULL but be
> freed during that call, resulting in UAF.
> 
> This affects xfs at this point, but the fuse extent map patchset[1]
> also adds dax failure handling and is affected by this issue.
> 
> I think this should be fixed in drivers/dax/super.c, since this will
> be a problem in each user.

Yes, I would have thought that the notification code would grab a
refcount on the dax device so that it can't go away.  Though it does
seem a little wild that there's no means to pause fs_dax_put until
all the notifications have cleared....?

--D

> Thanks,
> Miklos
> 
> [1] Report from sashiko (select Patch 8):
> 
> https://sashiko.dev/#/patchset/20260922061019.3320196-1-mszeredi%40redhat.com
> 
> Or here it is inline:
> 
> commit 1580a2f8ad3f103a20b6280aa39a01f8b0be2d3f
> Author: Miklos Szeredi <mszeredi@redhat.com>
> 
> fuse: add support for opening dax device as backing
> 
> Add FUSE_BACKING_IS_DEV flag that allows opening a character device
> (dax device) as a backing, in addition to regular files. Mark the
> inode with S_DAX if FUSE_LOOKUP returns with FUSE_ATTR_DAX set.
> 
> > diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c
> > index 58dbdd17c1ef4..aa558a0c2e647 100644
> > --- a/fs/fuse/backing.c
> > +++ b/fs/fuse/backing.c
> [ ... ]
> > @@ -22,9 +23,16 @@ static void fuse_backing_free(struct fuse_backing *fb)
> >  {
> >   pr_debug("%s: fb=0x%p\n", __func__, fb);
> >
> > - if (fb->file)
> > - fput(fb->file);
> > - put_cred(fb->cred);
> > + switch (fb->type) {
> > + case FUSE_BACKING_PATH:
> > + path_put(&fb->path);
> > + put_cred(fb->cred);
> > + break;
> > +
> > + case FUSE_BACKING_DAXDEV:
> > + fs_put_dax(fb->dax_dev, fb);
> > + break;
> > + }
> >   kfree_rcu(fb, rcu);
> 
> Does this code introduce a use-after-free race with a concurrent hardware
> memory failure?
> 
> When a DAX-backed FUSE backing file is closed, fuse_backing_free() drops the
> DAX device holder by calling fs_put_dax() and frees the backing object using
> normal RCU via kfree_rcu().
> 
> Concurrently, a hardware memory failure can trigger dax_holder_notify_failure(),
> which protects its read-side critical section with SRCU using dax_read_lock().
> 
> If dax_holder_notify_failure() reads dax_dev->holder_ops and checks for NULL,
> and is preempted here, fs_put_dax() can run to completion. This would set
> dax_dev->holder_ops and dax_dev->holder_data to NULL, and eventually free fb
> after a normal RCU grace period.
> 
> Because kfree_rcu() does not wait for SRCU readers, the memory could be freed
> while dax_holder_notify_failure() is still running.
> 
> [ ... ]
> > @@ -79,23 +87,88 @@ static struct fuse_backing *fuse_backing_id_remove(struct fuse_conn *fc, u64 id,
> >   return fb;
> >  }
> >
> > +static int fuse_dax_notify_failure(struct dax_device *daxdev, u64 offset, u64 len, int mf_flags)
> > +{
> > + struct fuse_backing *fb = dax_holder(daxdev);
> > +
> > + fb->dax_error = true;
> 
> Can this code cause a NULL pointer dereference or use-after-free when racing
> with fuse_backing_free()?
> 
> When dax_holder_notify_failure() resumes after the race described in
> fuse_backing_free(), it blindly calls ops->notify_failure() which is this
> function.
> 
> Because fs_put_dax() may have already cleared dax_dev->holder_data,
> dax_holder() might return NULL causing a NULL pointer dereference here.
> Depending on the timing, it could also return a stale pointer to the freed
> fb object, resulting in a use-after-free.
> 
> > +
> > + return 0;
> > +}
> 

      reply	other threads:[~2026-09-30 15:35 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-30 14:29 Miklos Szeredi
2026-09-30 15:35 ` Darrick J. Wong [this message]

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=20260930153506.GR6253@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=John@groves.net \
    --cc=alison.schofield@intel.com \
    --cc=cem@kernel.org \
    --cc=dave.jiang@intel.com \
    --cc=fuse-devel@lists.linux.dev \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=nvdimm@lists.linux.dev \
    --cc=vishal.l.verma@intel.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

all inboxes | Powered by JetHome®