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.