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

Konstantin Khorenko khorenko at virtuozzo.com
Mon Jun 15 14:15:51 MSK 2026


The commit is pushed to "branch-rh10-6.12.0-211.16.1.12.x.vz10-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-211.16.1.el10
------>
commit 56ef1ee0584ca6eb9bd9bfc790b78b1e6bdac6dc
Author: Konstantin Khorenko <khorenko at virtuozzo.com>
Date:   Thu Jun 4 00:05:00 2026 +0200

    fuse: lock the input-queue lock when walking pending_req in fusectl
    
    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: ee0d26ce7444 ("fuse: Show active requests in fusectl files")
    https://virtuozzo.atlassian.net/browse/VSTOR-132310
    Feature: vStorage
    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:


More information about the Devel mailing list