From: Cen Zhang <zzzccc427@gmail.com>
To: steffen.klassert@secunet.com, herbert@gondor.apana.org.au,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com
Cc: horms@kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, baijiaju1990@gmail.com,
jjzuming@gmail.com, zzzccc427@gmail.com
Subject: [PATCH ipsec 1/2] xfrm: keep old state references until migration deletion completes
Date: Sat, 31 Oct 2026 12:14:54 +0800 [thread overview]
Message-ID: <pm-xfrm-core-objects-candidate-0027-v3-cb1e033bff1976f510c9-1@gmail.com> (raw)
In-Reply-To: <pm-xfrm-core-objects-candidate-0027-v3-cb1e033bff1976f510c9-0@gmail.com>
xfrm_migrate() must retain the references returned by
xfrm_migrate_state_find() until it finishes using the old states. The
successful migration path instead calls xfrm_states_put() before
xfrm_states_delete(), leaving the latter to use unreferenced pointers
from x_cur[].
With CONFIG_XFRM_MIGRATE enabled, a privileged XFRM_MSG_MIGRATE or
SADB_X_MIGRATE request can reach this path for an SA with a finite hard
lifetime and no other users. If migration is preempted after the put,
the old SA can expire and be reclaimed before deletion resumes:
Migration task Hard-expiry timer / GC worker
-------------- -----------------------------
xfrm_migrate_state_find()
hold old SA in x_cur[]
migrate state and policy
xfrm_states_put(x_cur, ...)
drop lookup reference
xfrm_timer_handler()
__xfrm_state_delete(old SA)
drop SAD reference
xfrm_state_gc_task()
synchronize_rcu()
free old SA
xfrm_states_delete(x_cur, ...)
xfrm_state_delete(old SA)
spin_lock_bh(&x->lock) /* use after free */
The configuration mutex does not serialize migration with the timer or
GC worker, and migration holds no RCU read lock across this interval.
xfrm_state_delete() accesses the freed lock before it can check whether
the state is already dead. Expiry before the migration put can open the
same window, with that put dropping the last reference.
Delete the old states before putting their lookup references. Each state
then remains allocated through the lock access and the dead-state check,
including when expiry has already removed it from the SAD.
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in _raw_spin_lock_bh+0x38/0x50
Read of size 1 at addr ffff88810967af48 by task python3/443
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
kasan_report+0xe0/0x110
__kasan_check_byte+0x36/0x50
lock_acquire+0x113/0x2f0
_raw_spin_lock_bh+0x38/0x50
xfrm_state_delete+0x26/0x60
xfrm_migrate+0xd26/0x1950
xfrm_do_migrate+0x797/0xad0
xfrm_user_rcv_msg+0x3b3/0xc20
netlink_rcv_skb+0x133/0x390
xfrm_netlink_rcv+0x76/0x90
netlink_unicast+0x504/0x840
netlink_sendmsg+0x7f7/0xcf0
__sys_sendto+0x425/0x470
__x64_sys_sendto+0xe5/0x1c0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>
Allocated by task 424:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_slab_alloc+0x89/0x90
kmem_cache_alloc_noprof+0x20b/0x5f0
xfrm_state_alloc+0x28/0x5d0
xfrm_add_sa+0xb81/0x5660
xfrm_user_rcv_msg+0x3b3/0xc20
netlink_rcv_skb+0x133/0x390
xfrm_netlink_rcv+0x76/0x90
netlink_unicast+0x504/0x840
netlink_sendmsg+0x7f7/0xcf0
____sys_sendmsg+0x88b/0x9d0
___sys_sendmsg+0x125/0x1d0
__sys_sendmsg+0x13e/0x1e0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 66:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kmem_cache_free+0x242/0x580
xfrm_state_gc_task+0x534/0x780
process_one_work+0x908/0x19c0
worker_thread+0x65c/0xe40
kthread+0x34f/0x460
ret_from_fork+0x659/0x940
ret_from_fork_asm+0x1a/0x30
The buggy address belongs to the object at ffff88810967aec0
which belongs to the cache xfrm_state of size 936
The buggy address is located 136 bytes inside of
freed 936-byte region [ffff88810967aec0, ffff88810967b268)
==================================================================
Fixes: 80c9abaabf42 ("[XFRM]: Extension for dynamic update of endpoint address(es)")
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
Assisted-by: LLM
net/xfrm/xfrm_policy.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 0f6fcea28bcd..55f6bacc4e51 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -4726,8 +4726,8 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
/* Stage 4 - delete old state(s) */
if (nx_cur) {
- xfrm_states_put(x_cur, nx_cur);
xfrm_states_delete(x_cur, nx_cur);
+ xfrm_states_put(x_cur, nx_cur);
}
/* Stage 5 - announce */
next prev parent reply other threads:[~2026-10-31 4:15 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-31 4:14 [PATCH ipsec 0/2] xfrm: fix state lifetimes in xfrm_migrate() Cen Zhang
2026-10-31 4:14 ` Cen Zhang [this message]
2026-10-31 4:14 ` [PATCH ipsec 2/2] xfrm: hold migrated states through rollback Cen Zhang
2026-10-31 4:18 ` [PATCH ipsec 0/2] xfrm: fix state lifetimes in xfrm_migrate() netdev-bot+sinfo
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=pm-xfrm-core-objects-candidate-0027-v3-cb1e033bff1976f510c9-1@gmail.com \
--to=zzzccc427@gmail.com \
--cc=baijiaju1990@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=herbert@gondor.apana.org.au \
--cc=horms@kernel.org \
--cc=jjzuming@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=steffen.klassert@secunet.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®