All of lore.kernel.org
 help / color / mirror / Atom feed
From: Trond Myklebust <trondmy@hammerspace.com>
To: "okorniev@redhat.com" <okorniev@redhat.com>,
	"jlayton@kernel.org" <jlayton@kernel.org>,
	"chuck.lever@oracle.com" <chuck.lever@oracle.com>
Cc: "linux-nfs@vger.kernel.org" <linux-nfs@vger.kernel.org>,
	"stable@vger.kernel.org" <stable@vger.kernel.org>
Subject: Re: [PATCH 1/1] nfsd: fix race between laundromat and free_stateid
Date: Fri, 11 Oct 2024 13:14:32 +0000	[thread overview]
Message-ID: <541a46baa2eabd1a4d81520a7153617dd0a0fa7e.camel@hammerspace.com> (raw)
In-Reply-To: <ae0003013659a34279e3666180cd8b730ca3a2d8.camel@kernel.org>

On Fri, 2024-10-11 at 09:04 -0400, Jeff Layton wrote:
> On Thu, 2024-10-10 at 18:18 -0400, Olga Kornievskaia wrote:
> > There is a race between laundromat handling of revoked delegations
> > and a client sending free_stateid operation. Laundromat thread
> > finds that delegation has expired and needs to be revoked so it
> > marks the delegation stid revoked and it puts it on a reaper list
> > but then it unlock the state lock and the actual delegation
> > revocation
> > happens without the lock. Once the stid is marked revoked a racing
> > free_stateid processing thread does the following (1) it calls
> > list_del_init() which removes it from the reaper list and (2) frees
> > the delegation stid structure. The laundromat thread ends up not
> > calling the revoke_delegation() function for this particular
> > delegation
> > but that means it will no release the lock lease that exists on
> > the file.
> > 
> > Now, a new open for this file comes in and ends up finding that
> > lease list isn't empty and calls nfsd_breaker_owns_lease() which
> > ends
> > up trying to derefence a freed delegation stateid. Leading to the
> > followint use-after-free KASAN warning:
> > 
> > kernel:
> > ==================================================================
> > kernel: BUG: KASAN: slab-use-after-free in
> > nfsd_breaker_owns_lease+0x140/0x160 [nfsd]
> > kernel: Read of size 8 at addr ffff0000e73cd0c8 by task nfsd/6205
> > kernel:
> > kernel: CPU: 2 UID: 0 PID: 6205 Comm: nfsd Kdump: loaded Not
> > tainted 6.11.0-rc7+ #9
> > kernel: Hardware name: Apple Inc. Apple Virtualization Generic
> > Platform, BIOS 2069.0.0.0.0 08/03/2024
> > kernel: Call trace:
> > kernel: dump_backtrace+0x98/0x120
> > kernel: show_stack+0x1c/0x30
> > kernel: dump_stack_lvl+0x80/0xe8
> > kernel: print_address_description.constprop.0+0x84/0x390
> > kernel: print_report+0xa4/0x268
> > kernel: kasan_report+0xb4/0xf8
> > kernel: __asan_report_load8_noabort+0x1c/0x28
> > kernel: nfsd_breaker_owns_lease+0x140/0x160 [nfsd]
> > kernel: leases_conflict+0x68/0x370
> > kernel: __break_lease+0x204/0xc38
> > kernel: nfsd_open_break_lease+0x8c/0xf0 [nfsd]
> > kernel: nfsd_file_do_acquire+0xb3c/0x11d0 [nfsd]
> > kernel: nfsd_file_acquire_opened+0x84/0x110 [nfsd]
> > kernel: nfs4_get_vfs_file+0x634/0x958 [nfsd]
> > kernel: nfsd4_process_open2+0xa40/0x1a40 [nfsd]
> > kernel: nfsd4_open+0xa08/0xe80 [nfsd]
> > kernel: nfsd4_proc_compound+0xb8c/0x2130 [nfsd]
> > kernel: nfsd_dispatch+0x22c/0x718 [nfsd]
> > kernel: svc_process_common+0x8e8/0x1960 [sunrpc]
> > kernel: svc_process+0x3d4/0x7e0 [sunrpc]
> > kernel: svc_handle_xprt+0x828/0xe10 [sunrpc]
> > kernel: svc_recv+0x2cc/0x6a8 [sunrpc]
> > kernel: nfsd+0x270/0x400 [nfsd]
> > kernel: kthread+0x288/0x310
> > kernel: ret_from_fork+0x10/0x20
> > 
> > Proposing to have laundromat thread hold the state_lock over both
> > marking thru revoking the delegation as well as making free_stateid
> > acquire state_lock before accessing the list. Making sure that
> > revoke_delegation() (ie kernel_setlease(unlock)) is called for
> > every delegation that was revoked and added to the reaper list.
> > 
> 
> Nice detective work!
> 
> > CC: stable@vger.kernel.org
> > Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
> > 
> > --- I can't figure out the Fixes: tag. Laundromat's behaviour has
> > been like that forever. But the free_stateid bits wont apply before
> > the 1e3577a4521e ("SUNRPC: discard sv_refcnt, and
> > svc_get/svc_put").
> > But we used that fixes tag already with a previous fix for a
> > different
> > problem.
> > ---
> >  fs/nfsd/nfs4state.c | 4 +++-
> >  1 file changed, 3 insertions(+), 1 deletion(-)
> > 
> > diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> > index 9c2b1d251ab3..c97907d7fb38 100644
> > --- a/fs/nfsd/nfs4state.c
> > +++ b/fs/nfsd/nfs4state.c
> > @@ -6605,13 +6605,13 @@ nfs4_laundromat(struct nfsd_net *nn)
> >  		unhash_delegation_locked(dp, SC_STATUS_REVOKED);
> >  		list_add(&dp->dl_recall_lru, &reaplist);
> >  	}
> > -	spin_unlock(&state_lock);
> >  	while (!list_empty(&reaplist)) {
> >  		dp = list_first_entry(&reaplist, struct
> > nfs4_delegation,
> >  					dl_recall_lru);
> >  		list_del_init(&dp->dl_recall_lru);
> >  		revoke_delegation(dp);
> >  	}
> > +	spin_unlock(&state_lock);
> >  
> >  	spin_lock(&nn->client_lock);
> >  	while (!list_empty(&nn->close_lru)) {
> > @@ -7213,7 +7213,9 @@ nfsd4_free_stateid(struct svc_rqst *rqstp,
> > struct nfsd4_compound_state *cstate,
> >  		if (s->sc_status & SC_STATUS_REVOKED) {
> >  			spin_unlock(&s->sc_lock);
> >  			dp = delegstateid(s);
> > +			spin_lock(&state_lock);
> >  			list_del_init(&dp->dl_recall_lru);
> > +			spin_unlock(&state_lock);
> >  			spin_unlock(&cl->cl_lock);

nfs4_set_delegation() takes these locks in the opposite order, so as it
stands, this patch introduces a potential ABBA deadlock.
I suggest moving the state_lock so that it is taken before and released
after the cl->cl_lock.


> >  			nfs4_put_stid(s);
> >  			ret = nfs_ok;
> 
> 
> I'm not thrilled with this patch, but it does seem like it would fix
> the problem. Long term, I think we need to get rid of the state_lock,
> but I don't have a real plan for that just yet as it's not 100% clear
> what it still protects.
> 
> As far as a Fixes tag, this bug is likely very old. I'd say it
> probably
> got introduced here:
> 
>     2d4a532d385f nfsd: ensure that clp->cl_revoked list is protected
> by clp->cl_lock
> 
> In any case, let's go with this patch until we can come up with a
> better plan for delegation handling.
> 
> Reviewed-by: Jeff Layton <jlayton@kernel.org>
> 

-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@hammerspace.com



  reply	other threads:[~2024-10-11 13:14 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-10 22:18 [PATCH 1/1] nfsd: fix race between laundromat and free_stateid Olga Kornievskaia
2024-10-11 13:04 ` Jeff Layton
2024-10-11 13:14   ` Trond Myklebust [this message]
2024-10-11 13:43     ` Olga Kornievskaia
2024-10-11 13:59   ` Olga Kornievskaia
2024-10-11 14:39 ` Chuck Lever
2024-10-11 16:17   ` Jeff Layton
2024-10-11 20:01     ` Olga Kornievskaia
2024-10-11 20:16       ` Jeff Layton
2024-10-11 20:57         ` Olga Kornievskaia
2024-10-11 20:57   ` Trond Myklebust

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=541a46baa2eabd1a4d81520a7153617dd0a0fa7e.camel@hammerspace.com \
    --to=trondmy@hammerspace.com \
    --cc=chuck.lever@oracle.com \
    --cc=jlayton@kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=okorniev@redhat.com \
    --cc=stable@vger.kernel.org \
    /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.