Ack On Thu, Jun 4, 2026 at 5:56 PM Konstantin Khorenko <[email protected]> wrote: > > The fusectl "pending_req" seq-file iterates conn->main_iq.pending, but > fuse_req_start()/fuse_req_stop() took conn->lock. The pending list of a > fuse_iqueue is added to and removed from under the iqueue's own lock > (fiq->lock, i.e. conn->main_iq.lock) in fuse_dev_queue_req() and the > device read path - not under conn->lock. So the reader walked a live > list with no synchronisation against concurrent enqueue/dequeue, which > can corrupt the iteration / crash. > > Store the lock that protects the list alongside req_list in > fuse_conn_priv and take it in start/stop; for pending_req that is > conn->main_iq.lock. (The #if 0 processing/io variants get their matching > pq.lock so they stay correct if ever re-enabled.) > > The file is mode 0600 (root only) and needs concurrent fuse traffic to > race, so impact is limited to a diagnostic interface. > > Fixes: 22495d9d1f53 ("fuse: Show active requests in fusectl files") > https://virtuozzo.atlassian.net/browse/VSTOR-132310 > Signed-off-by: Konstantin Khorenko <[email protected]> > --- > fs/fuse/control.c | 9 +++++++-- > 1 file changed, 7 insertions(+), 2 deletions(-) > > diff --git a/fs/fuse/control.c b/fs/fuse/control.c > index 92682f33d457..1f5d998be23d 100644 > --- a/fs/fuse/control.c > +++ b/fs/fuse/control.c > @@ -249,6 +249,8 @@ static const struct file_operations > fuse_conn_loglevel_ops = { > struct fuse_conn_priv { > struct fuse_conn *conn; > struct list_head *req_list; > + /* lock that protects @req_list against concurrent enqueue/dequeue */ > + spinlock_t *req_lock; > }; > > enum { > @@ -261,7 +263,7 @@ static void *fuse_req_start(struct seq_file *m, loff_t *p) > { > struct fuse_conn_priv *fcp = m->private; > > - spin_lock(&fcp->conn->lock); > + spin_lock(fcp->req_lock); > return seq_list_start(fcp->req_list, *p); > } > > @@ -274,7 +276,7 @@ static void *fuse_req_next(struct seq_file *m, void *v, > loff_t *p) > static void fuse_req_stop(struct seq_file *m, void *v) > { > struct fuse_conn_priv *fcp = m->private; > - spin_unlock(&fcp->conn->lock); > + spin_unlock(fcp->req_lock); > } > > static int fuse_req_show(struct seq_file *f, void *v) > @@ -331,13 +333,16 @@ static int fuse_conn_seq_open(struct file *filp, int > list_id) > switch (list_id) { > case FUSE_PENDING_REQ: > fcp->req_list = &conn->main_iq.pending; > + fcp->req_lock = &conn->main_iq.lock; > break; > #if 0 > case FUSE_PROCESSING_REQ: > fcp->req_list = &conn->pq.processing; > + fcp->req_lock = &conn->pq.lock; > break; > case FUSE_IO_REQ: > fcp->req_list = &conn->pq.io; > + fcp->req_lock = &conn->pq.lock; > break; > #endif > default: > -- > 2.47.1
_______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
