Re: [PATCH v3] fuse: fix uring race condition for null dereference of fc

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Mar 18, 2025 at 3:38 AM Bernd Schubert
<bernd.schubert@xxxxxxxxxxx> wrote:
>
>
>
> On 3/18/25 01:30, Joanne Koong wrote:
> > There is a race condition leading to a kernel crash from a null
> > dereference when attemping to access fc->lock in
> > fuse_uring_create_queue(). fc may be NULL in the case where another
> > thread is creating the uring in fuse_uring_create() and has set
> > fc->ring but has not yet set ring->fc when fuse_uring_create_queue()
> > reads ring->fc. There is another race condition as well where in
> > fuse_uring_register(), ring->nr_queues may still be 0 and not yet set
> > to the new value when we compare qid against it.
> >
> > This fix sets fc->ring only after ring->fc and ring->nr_queues have been
> > set, which guarantees now that ring->fc is a proper pointer when any
> > queues are created and ring->nr_queues reflects the right number of
> > queues if ring is not NULL. We must use smp_store_release() and
> > smp_load_acquire() semantics to ensure the ordering will remain correct
> > where fc->ring is assigned only after ring->fc and ring->nr_queues have
> > been assigned.
> >
> > Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx>
> > Fixes: 24fe962c86f5 ("fuse: {io-uring} Handle SQEs - register commands")
> >
> > ---
> >
> > Changes between v2 -> v3:
> > * v2 implementation still has race condition for ring->nr_queues
> > *link to v2: https://lore.kernel.org/linux-fsdevel/20250314205033.762641-1-joannelkoong@xxxxxxxxx/
> >
> > Changes between v1 -> v2:
> > * v1 implementation may be reordered by compiler (Bernd)
> > * link to v1: https://lore.kernel.org/linux-fsdevel/20250314191334.215741-1-joannelkoong@xxxxxxxxx/
> >
> > ---
> >  fs/fuse/dev_uring.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
> > index ab8c26042aa8..97e6d31479e0 100644
> > --- a/fs/fuse/dev_uring.c
> > +++ b/fs/fuse/dev_uring.c
> > @@ -235,11 +235,11 @@ static struct fuse_ring *fuse_uring_create(struct fuse_conn *fc)
> >
> >       init_waitqueue_head(&ring->stop_waitq);
> >
> > -     fc->ring = ring;
> >       ring->nr_queues = nr_queues;
> >       ring->fc = fc;
> >       ring->max_payload_sz = max_payload_size;
> >       atomic_set(&ring->queue_refs, 0);
> > +     smp_store_release(&fc->ring, ring);
> >
> >       spin_unlock(&fc->lock);
> >       return ring;
> > @@ -1068,7 +1068,7 @@ static int fuse_uring_register(struct io_uring_cmd *cmd,
> >                              unsigned int issue_flags, struct fuse_conn *fc)
> >  {
> >       const struct fuse_uring_cmd_req *cmd_req = io_uring_sqe_cmd(cmd->sqe);
> > -     struct fuse_ring *ring = fc->ring;
> > +     struct fuse_ring *ring = smp_load_acquire(&fc->ring);
> >       struct fuse_ring_queue *queue;
> >       struct fuse_ring_ent *ent;
> >       int err;
>
> I was actually debating with myself that smp_load_acquire() on Friday.
> I think we do not need it, because if the ring is not found, it will
> go into the spin lock. But it does not hurt either and it might
> cleaner to have a pair of smp_store_release() and smp_load_acquire().
>

I think the problem is that if we don't have it, then ring may be
non-null but the ring->nr_queues value we read in "if (qid >=
ring->nr_queues)" might still be the stale value, which would make the
uring registration fail with -EINVAL.

Thanks,
Joanne

>
> Reviewed-by: Bernd Schubert <bschubert@xxxxxxx>





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux