[Devel] [PATCH vz10] fuse: lock the input-queue lock when walking pending_req in fusectl

Alexey Kuznetsov kuznet at virtuozzo.com
Tue Jun 9 13:03:01 MSK 2026


Ack

On Thu, Jun 4, 2026 at 5:56 PM Konstantin Khorenko
<khorenko at virtuozzo.com> 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 <khorenko at virtuozzo.com>
> ---
>  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



More information about the Devel mailing list