From: Chuck Lever <chuck.lever@oracle.com>
To: Olga Kornievskaia <okorniev@redhat.com>
Cc: linux-nfs@vger.kernel.org, Jeff Layton <jlayton@kernel.org>,
rtm@csail.mit.edu
Subject: Re: use-after-free in nfs4stat.c _free_cpntf_state_locked()
Date: Fri, 3 Oct 2025 13:40:07 -0400 [thread overview]
Message-ID: <d8f064c1-a26f-4eed-b4f0-1f7f608f415f@oracle.com> (raw)
In-Reply-To: <83337.1759494865@localhost>
On 10/3/25 8:34 AM, rtm@csail.mit.edu wrote:
> If an NFS 4.2 client has a COPY_NOTIFY registered, and then
> re-establishes its session with EXCHANGE_ID with a new verifier and
> CREATE_SESSION, nfsd4_create_session() calls expire_client() for the
> old session, which frees the nfs4_stid associated with the
> COPY_NOTIFY. But the COPY_NOTIFY's nfs4_cpntf_state still exists; when
> nfs4_laundromat() expires it, _free_cpntf_state_locked()'s
> list_del(&cps->cp_list) uses the freed memory of the nfs4_stid.
>
> A demo:
>
> # uname -r
> 6.17.0-01737-g50c19e20ed2e-dirty
> # cat /etc/exports
> /tmp 127.0.0.1(rw,subtree_check,pnfs)
> # wget http://www.rtmrtm.org/rtm/nfsd185b.c
> # cc nfsd185b.c
> # ./a.out
> (wait 10 or 20 seconds for nfs4_laundromat())
> (you may have to run a.out more than once)
> list_del corruption. prev->next should be ffff8881068669d8, but was 6b6b6b6b6b6b6b6b. (prev=ffff888105190010)
> kernel BUG at lib/list_debug.c:62!
> Oops: invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC PTI
> CPU: 2 UID: 0 PID: 268 Comm: kworker/u51:2 Tainted: G W 6.17.0-01737-g50c19e20ed2e-dirty #33 PREEMPT(voluntary)
> Workqueue: nfsd4 laundromat_main
> RIP: 0010:__list_del_entry_valid_or_report+0xdd/0x110
> Call Trace:
> _free_cpntf_state_locked+0x40/0xb0
> laundromat_main+0x5ec/0xaf0
>
> The nfs4_cpntf_state is allocated and linked into the
> nfs4_stid.sc_cp_list here:
>
> #0 list_add (head=<optimized out>, new=<optimized out>)
> at fs/nfsd/nfs4state.c:985
> #1 nfs4_alloc_init_cpntf_state (nn=nn@entry=0xffffffd602d82000,
> p_stid=0xffffffd606858008) at fs/nfsd/nfs4state.c:985
> #2 0xffffffff804b04e0 in nfsd4_copy_notify (rqstp=0xffffffd6040fb800,
> cstate=<optimized out>, u=0xffffffd6052e2720) at fs/nfsd/nfs4proc.c:2078
> (gdb) print cps
> $1 = (struct nfs4_cpntf_state *) 0xffffffd603fe9020
> (gdb) print p_stid
> $2 = (struct nfs4_stid *) 0xffffffd606858008
>
> The nfs4_stid is freed here:
>
> #0 nfs4_free_ol_stateid (stid=0xffffffd606858008) at fs/nfsd/nfs4state.c:1502
> #1 0xffffffff804c3ed2 in free_ol_stateid_reaplist (
> reaplist=reaplist@entry=0xffffffc60031baf8) at fs/nfsd/nfs4state.c:1602
> #2 0xffffffff804c46fa in release_openowner (oo=0xffffffd606857008)
> at fs/nfsd/nfs4state.c:1696
> #3 0xffffffff804c4898 in __destroy_client (clp=clp@entry=0xffffffd605308008)
> at fs/nfsd/nfs4state.c:2483
> #4 0xffffffff804c49fa in expire_client (clp=0xffffffd605308008)
> at fs/nfsd/nfs4state.c:2533
> #5 0xffffffff804c7a26 in nfsd4_create_session (rqstp=0xffffffd6040fb800,
> cstate=<optimized out>, u=0xffffffd6052e2060) at fs/nfsd/nfs4state.c:4041
> (gdb) print stid
> $3 = (struct nfs4_stid *) 0xffffffd606858008
> (gdb) print stid->sc_cp_list
> $4 = {next = 0xffffffd603fe9038, prev = 0xffffffd603fe9038}
>
> Freeing the nfs4_cpntf_state trips over the free nfs4_stid here:
>
> #0 _free_cpntf_state_locked (nn=nn@entry=0xffffffd602d82000,
> cps=0xffffffd603fe9020) at fs/nfsd/nfs4state.c:7226
> #1 0xffffffff804c6210 in nfs4_laundromat (nn=0xffffffd602d82000)
> at fs/nfsd/nfs4state.c:6836
> #2 laundromat_main (laundry=0xffffffd602d820d0) at fs/nfsd/nfs4state.c:6926
> (gdb) print cps
> $5 = (struct nfs4_cpntf_state *) 0xffffffd603fe9020
> (gdb) print cps->cp_list
> $6 = {next = 0xffffffd606858010, prev = 0xffffffd606858010}
> (gdb) print cps->cp_list.next.prev
> $7 = (struct list_head *) 0x6b6b6b6b6b6b6b6b
>
> Robert Morris
> rtm@mit.edu
Olga, do you have a few moments to triage this?
--
Chuck Lever
prev parent reply other threads:[~2025-10-03 17:40 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-03 12:34 use-after-free in nfs4stat.c _free_cpntf_state_locked() rtm
2025-10-03 17:40 ` Chuck Lever [this message]
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=d8f064c1-a26f-4eed-b4f0-1f7f608f415f@oracle.com \
--to=chuck.lever@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=okorniev@redhat.com \
--cc=rtm@csail.mit.edu \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox