Skip to content

Commit e0cc481

Browse files
Dong Chenchengregkh
Dong Chenchen
authored andcommitted
net: xfrm: skip policies marked as dead while reinserting policies
commit 6d41d4f upstream. BUG: KASAN: slab-use-after-free in xfrm_policy_inexact_list_reinsert+0xb6/0x430 Read of size 1 at addr ffff8881051f3bf8 by task ip/668 CPU: 2 PID: 668 Comm: ip Not tainted 6.5.0-rc5-00182-g25aa0bebba72-dirty #64 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x72/0xa0 print_report+0xd0/0x620 kasan_report+0xb6/0xf0 xfrm_policy_inexact_list_reinsert+0xb6/0x430 xfrm_policy_inexact_insert_node.constprop.0+0x537/0x800 xfrm_policy_inexact_alloc_chain+0x23f/0x320 xfrm_policy_inexact_insert+0x6b/0x590 xfrm_policy_insert+0x3b1/0x480 xfrm_add_policy+0x23c/0x3c0 xfrm_user_rcv_msg+0x2d0/0x510 netlink_rcv_skb+0x10d/0x2d0 xfrm_netlink_rcv+0x49/0x60 netlink_unicast+0x3fe/0x540 netlink_sendmsg+0x528/0x970 sock_sendmsg+0x14a/0x160 ____sys_sendmsg+0x4fc/0x580 ___sys_sendmsg+0xef/0x160 __sys_sendmsg+0xf7/0x1b0 do_syscall_64+0x3f/0x90 entry_SYSCALL_64_after_hwframe+0x73/0xdd The root cause is: cpu 0 cpu1 xfrm_dump_policy xfrm_policy_walk list_move_tail xfrm_add_policy ... ... xfrm_policy_inexact_list_reinsert list_for_each_entry_reverse if (!policy->bydst_reinsert) //read non-existent policy xfrm_dump_policy_done xfrm_policy_walk_done list_del(&walk->walk.all); If dump_one_policy() returns err (triggered by netlink socket), xfrm_policy_walk() will move walk initialized by socket to list net->xfrm.policy_all. so this socket becomes visible in the global policy list. The head *walk can be traversed when users add policies with different prefixlen and trigger xfrm_policy node merge. The issue can also be triggered by policy list traversal while rehashing and flushing policies. It can be fixed by skip such "policies" with walk.dead set to 1. Fixes: 9cf545e ("xfrm: policy: store inexact policies in a tree ordered by destination address") Fixes: 12a169e ("ipsec: Put dumpers on the dump list") Signed-off-by: Dong Chenchen <[email protected]> Signed-off-by: Steffen Klassert <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 071bba3 commit e0cc481

File tree

1 file changed

+13
-6
lines changed

1 file changed

+13
-6
lines changed

net/xfrm/xfrm_policy.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
851851
struct hlist_node *newpos = NULL;
852852
bool matches_s, matches_d;
853853

854-
if (!policy->bydst_reinsert)
854+
if (policy->walk.dead || !policy->bydst_reinsert)
855855
continue;
856856

857857
WARN_ON_ONCE(policy->family != family);
@@ -1256,8 +1256,11 @@ static void xfrm_hash_rebuild(struct work_struct *work)
12561256
struct xfrm_pol_inexact_bin *bin;
12571257
u8 dbits, sbits;
12581258

1259+
if (policy->walk.dead)
1260+
continue;
1261+
12591262
dir = xfrm_policy_id2dir(policy->index);
1260-
if (policy->walk.dead || dir >= XFRM_POLICY_MAX)
1263+
if (dir >= XFRM_POLICY_MAX)
12611264
continue;
12621265

12631266
if ((dir & XFRM_POLICY_MASK) == XFRM_POLICY_OUT) {
@@ -1821,9 +1824,11 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
18211824

18221825
again:
18231826
list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) {
1827+
if (pol->walk.dead)
1828+
continue;
1829+
18241830
dir = xfrm_policy_id2dir(pol->index);
1825-
if (pol->walk.dead ||
1826-
dir >= XFRM_POLICY_MAX ||
1831+
if (dir >= XFRM_POLICY_MAX ||
18271832
pol->type != type)
18281833
continue;
18291834

@@ -1860,9 +1865,11 @@ int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
18601865

18611866
again:
18621867
list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) {
1868+
if (pol->walk.dead)
1869+
continue;
1870+
18631871
dir = xfrm_policy_id2dir(pol->index);
1864-
if (pol->walk.dead ||
1865-
dir >= XFRM_POLICY_MAX ||
1872+
if (dir >= XFRM_POLICY_MAX ||
18661873
pol->xdo.dev != dev)
18671874
continue;
18681875

0 commit comments

Comments
 (0)