All of lore.kernel.org
 help / color / mirror / Atom feed
From: Abdifatah Suruur <suruurism@gmail.com>
To: cel@kernel.org, jlayton@kernel.org
Cc: linux-nfs@vger.kernel.org, NeilBrown <neil@brown.name>,
	Olga Kornievskaia <okorniev@redhat.com>,
	Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org,
	Abdifatah Suruur <suruurism@gmail.com>
Subject: [PATCH] lockd: fix use-after-free in nlmsvc_retry_blocked()
Date: Wed, 30 Sep 2026 23:22:12 +0300	[thread overview]
Message-ID: <20260930202212.1482-1-suruurism@gmail.com> (raw)

A block queued on the nlm_blocked list holds exactly one kref, the
list's: nlmsvc_create_block() hands out an initial reference,
nlmsvc_insert_block_locked() takes the list reference, and
nlmsvc_lock() releases the initial one at out:.

nlmsvc_retry_blocked() then drops nlm_blocked_lock and dereferences
`block` (b_when, b_flags, b_deferred_req) and passes it to
retry_deferred_block() or nlmsvc_grant_blocked() without holding any
reference of its own.  Concurrently, an svc thread processing the
client's GRANT_RES (nlmsvc_grant_reply()), a CANCEL or UNLOCK
(nlmsvc_cancel_blocked()), or a host failover sweep
(nlmsvc_traverse_blocks()) can find the same block, unlink it and drop
the last kref, freeing it while the lockd kthread is still using the
pointer.  The freed slab is then written through: kref_get() on the
freed block, the B_TIMED_OUT flag, the list operations in
nlmsvc_insert_block(), and the b_deferred_req revisit - a
use-after-free on a remotely reachable path.

nlmsvc_notify_blocked() has the same problem: it moves the block to
the head of the list and then calls svc_wake_up(block->b_daemon)
after dropping nlm_blocked_lock.  Keep that wake-up under the
spinlock, as nlmsvc_grant_deferred() already does.

Pin the block before dropping the spinlock in nlmsvc_retry_blocked()
and release the pin after processing, so the block cannot be freed
while it is in use.

Cc: stable@vger.kernel.org
Signed-off-by: Abdifatah Suruur <suruurism@gmail.com>
---
 fs/lockd/svclock.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index e628b5d355071..38d02b10591ae 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -775,8 +775,8 @@ nlmsvc_notify_blocked(struct file_lock *fl)
 	list_for_each_entry(block, &nlm_blocked, b_list) {
 		if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
 			nlmsvc_insert_block_locked(block, 0);
-			spin_unlock(&nlm_blocked_lock);
 			svc_wake_up(block->b_daemon);
+			spin_unlock(&nlm_blocked_lock);
 			return;
 		}
 	}
@@ -1023,6 +1023,13 @@ nlmsvc_retry_blocked(struct svc_rqst *rqstp)
 			timeout = block->b_when - jiffies;
 			break;
 		}
+		/*
+		 * Pin the block before dropping nlm_blocked_lock: a
+		 * concurrent GRANT_RES, CANCEL or UNLOCK can unlink the
+		 * block and drop the last kref, freeing it while we are
+		 * still using it.
+		 */
+		kref_get(&block->b_count);
 		spin_unlock(&nlm_blocked_lock);
 
 		dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
@@ -1033,6 +1040,7 @@ nlmsvc_retry_blocked(struct svc_rqst *rqstp)
 			retry_deferred_block(block);
 		} else
 			nlmsvc_grant_blocked(block);
+		nlmsvc_release_block(block);
 		spin_lock(&nlm_blocked_lock);
 	}
 	spin_unlock(&nlm_blocked_lock);
-- 
2.53.0


             reply	other threads:[~2026-09-30 20:22 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-30 20:22 Abdifatah Suruur [this message]
2026-10-01  1:07 ` [PATCH] lockd: fix use-after-free in nlmsvc_retry_blocked() Chuck Lever
2026-10-15 17:28   ` Abdifatah Suruur

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260930202212.1482-1-suruurism@gmail.com \
    --to=suruurism@gmail.com \
    --cc=Dai.Ngo@oracle.com \
    --cc=cel@kernel.org \
    --cc=jlayton@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=neil@brown.name \
    --cc=okorniev@redhat.com \
    --cc=stable@vger.kernel.org \
    --cc=tom@talpey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.