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 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.