On Mon, Oct 5, 2026 at 3:33 PM Miklos Szeredi <[email protected]> wrote:

> > > It would feel a little less hacky if we do:
> > >     else
> > >           fuse_backing_files_init_32(fc);
> > >
> > > and set
> > >          fc->passthrough = 1;
> > >
> > > inside both of them to gate against fuse_backing_files_free()
> > > called without processing init response,
> > > or without either FUSE_PASSTHROUGH in the init response.
>
> Bigger problem is that IOC_BACKING_OPEN can be done before or during
> INIT.  So we need to take care of that case and the race as well.
> Fixed by:
>
>  - leaving the idr initialization fuse_conn_init()
>
>  - adding fc->backing_id_32 flag which is set by fuse_backing_open()
> after chekcking that fc->backing_id_64 is not set.  All under fc->lock
>
>  - in process_init_reply() checking fc->backing_id_32 before setting
> fc->backing_id_64 and failing the connection if so.  Also under
> fc->lock
>
>  - in fuse_dev_ioctl_backing_create() if fch->initialized is not set
> return ENOTCONN
>

I guess that works, but why the asymmetry between the two modes?

We could check fch->initialized in both _open() and _create()
and then no need for the backing_id_32 flag?

Unless we gate _open() with fch->initialized, then it could fail on
either one of these cases:

                if (!fc->passthrough || !capable(CAP_SYS_ADMIN))
                        return -EPERM;

                if (inode->i_sb->s_stack_depth >= fc->max_stack_depth)
                        return -ELOOP;

Quite randomly.

Maybe I am missing something.

Thanks,
Amir.

Reply via email to