From: rtm@csail.mit.edu
To: Chuck Lever <chuck.lever@oracle.com>, Jeff Layton <jlayton@kernel.org>
Cc: linux-nfs@vger.kernel.org
Subject: use-after-free in nfs4stat.c _free_cpntf_state_locked()
Date: Fri, 03 Oct 2025 08:34:25 -0400 [thread overview]
Message-ID: <83337.1759494865@localhost> (raw)
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
next reply other threads:[~2025-10-03 12:40 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-03 12:34 rtm [this message]
2025-10-03 17:40 ` use-after-free in nfs4stat.c _free_cpntf_state_locked() Chuck Lever
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=83337.1759494865@localhost \
--to=rtm@csail.mit.edu \
--cc=chuck.lever@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox