[PATCH ipsec v2] xfrm: reject optional IPTFS templates in outbound policies
From: Antony Antony <hidden>
Date: 2026-06-27 08:23:59
Subsystem:
networking [general], networking [ipsec], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Steffen Klassert, Herbert Xu, Linus Torvalds
syzbot reported a stack-out-of-bounds read in xfrm_state_find()
which flows from xfrm_tmpl_resolve_one().
Commit 3d776e31c841 ("xfrm: Reject optional tunnel/BEET mode
templates in outbound policies") disallowed optional tunnel and
BEET in outbound policies to prevent this. Later when IPTFS
added, it was not covered by that fix and can still trigger
the out-of-bounds read;
Extend the check to disallow optional IPTFS in outbound policies
as well. IPTFS should be identical to tunnel mode.
IN and FWD policies are not affected: xfrm_tmpl_resolve_one()
is only reachable via the outbound path.
Reproducer, before:
ip link add dummy0 type dummy
ip link set dummy0 up
ip addr add 10.1.1.1/24 dev dummy0
ip xfrm policy add src 10.1.1.1/32 dst 10.1.1.2/32 dir out tmpl
src fc00::dead:1 dst fc00::dead:2 proto esp reqid 1 mode iptfs
level use tmpl src fc00::dead:1 dst fc00::dead:2 proto esp reqid
2 mode transport
ping -W 1 -c 1 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
[ 64.168420] ==================================================================
[ 64.169977] BUG: KASAN: stack-out-of-bounds in __xfrm6_addr_hash+0x11e/0x170
[ 64.169977] Read of size 4 at addr ffff88800e1ffd20 by task ping/2844
[ 64.169977] CPU: 2 UID: 0 PID: 2844 Comm: ping Not tainted 7.1.0-rc7-00180-geb23b588430a #98 PREEMPT(full)
[ 64.169977] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 64.169977] Call Trace:
[ 64.169977] <TASK>
[ 64.169977] dump_stack_lvl+0x47/0x70
[ 64.169977] ? __xfrm6_addr_hash+0x11e/0x170
[ 64.169977] print_report+0x152/0x4b0
[ 64.169977] ? ksys_mmap_pgoff+0x6d/0xa0
[ 64.169977] ? entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 64.169977] ? rcu_read_unlock_sched+0xa/0x20
[ 64.169977] ? __virt_addr_valid+0x21b/0x230
[ 64.169977] ? __xfrm6_addr_hash+0x11e/0x170
[ 64.169977] kasan_report+0xa8/0xd0
[ 64.169977] ? __xfrm6_addr_hash+0x11e/0x170
[ 64.169977] __xfrm6_addr_hash+0x11e/0x170
[ 64.169977] __xfrm_dst_hash+0x24/0xc0
[ 64.169977] xfrm_state_find+0xa2d/0x2f90
[ 64.169977] ? __pfx_xfrm_state_find+0x10/0x10
[ 64.169977] ? __pfx_ftrace_graph_ret_addr+0x10/0x10
[ 64.169977] ? __pfx_ftrace_graph_ret_addr+0x10/0x10
[ 64.169977] xfrm_tmpl_resolve_one+0x210/0x570
[ 64.169977] ? __pfx_xfrm_tmpl_resolve_one+0x10/0x10
[ 64.169977] ? __pfx_stack_trace_consume_entry+0x10/0x10
[ 64.169977] ? kernel_text_address+0x5b/0x80
[ 64.169977] ? __kernel_text_address+0xe/0x30
[ 64.169977] ? unwind_get_return_address+0x5e/0x90
[ 64.169977] ? arch_stack_walk+0x8c/0xe0
[ 64.169977] xfrm_tmpl_resolve+0x130/0x200
[ 64.169977] ? __pfx_xfrm_tmpl_resolve+0x10/0x10
[ 64.169977] ? __pfx_xfrm_policy_inexact_lookup_rcu+0x10/0x10
[ 64.169977] ? __refcount_add_not_zero.constprop.0+0xb2/0x110
[ 64.169977] ? __pfx___refcount_add_not_zero.constprop.0+0x10/0x10
[ 64.169977] xfrm_resolve_and_create_bundle+0xd5/0x310
[ 64.169977] ? __pfx_xfrm_resolve_and_create_bundle+0x10/0x10
[ 64.169977] ? __pfx_xfrm_policy_lookup_bytype+0x10/0x10
[ 64.169977] ? __pfx_xfrm_policy_lookup_bytype+0x10/0x10
[ 64.169977] xfrm_lookup_with_ifid+0x3d8/0xb80
[ 64.169977] ? __pfx_xfrm_lookup_with_ifid+0x10/0x10
[ 64.169977] ? ip_route_output_key_hash+0xc6/0x110
[ 64.169977] ? kasan_save_track+0x10/0x30
[ 64.169977] xfrm_lookup_route+0x18/0xe0
[ 64.169977] ip4_datagram_release_cb+0x4c9/0x530
[ 64.169977] ? __pfx_ip4_datagram_release_cb+0x10/0x10
[ 64.169977] ? do_raw_spin_lock+0x71/0xc0
[ 64.169977] ? __pfx_do_raw_spin_lock+0x10/0x10
[ 64.169977] release_sock+0xb0/0x170
[ 64.169977] udp_connect+0x43/0x50
[ 64.169977] __sys_connect+0xa6/0x100
[ 64.169977] ? alloc_fd+0x2e9/0x300
[ 64.169977] ? __pfx___sys_connect+0x10/0x10
[ 64.169977] ? preempt_latency_start+0x1f/0x70
[ 64.169977] ? fd_install+0x7e/0x150
[ 64.169977] ? rcu_read_unlock_sched+0xa/0x20
[ 64.169977] ? __sys_socket+0xdf/0x130
[ 64.169977] ? __pfx___sys_socket+0x10/0x10
[ 64.169977] ? vma_refcount_put+0x43/0xa0
[ 64.169977] __x64_sys_connect+0x7e/0x90
[ 64.169977] do_syscall_64+0x11b/0x2b0
[ 64.169977] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 64.169977] RIP: 0033:0x7f4851ecb570
[ 64.169977] Code: 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 80 3d f9 ca 0d 00 00 74 17 b8 2a 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 58 c3 0f 1f 80 00 00 00 00 48 83 ec 18 89 54
[ 64.169977] RSP: 002b:00007ffc830e3498 EFLAGS: 00000202 ORIG_RAX: 000000000000002a
[ 64.169977] RAX: ffffffffffffffda RBX: 00007ffc830e34d0 RCX: 00007f4851ecb570
[ 64.169977] RDX: 0000000000000010 RSI: 00007ffc830e34d0 RDI: 0000000000000005
[ 64.169977] RBP: 0000000000000000 R08: 0000000000000003 R09: 0000000000000000
[ 64.169977] R10: 0000000000000006 R11: 0000000000000202 R12: 0000000000000005
[ 64.169977] R13: 0000000000000000 R14: 00005619a863f340 R15: 0000000000000000
[ 64.169977] </TASK>
[ 64.169977] The buggy address belongs to stack of task ping/2844
[ 64.169977] and is located at offset 88 in frame:
[ 64.169977] ip4_datagram_release_cb+0x0/0x530
[ 64.169977] This frame has 1 object:
[ 64.169977] [32, 88) 'fl4'
[ 64.169977] The buggy address belongs to the physical page:
[ 64.169977] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0xe1ff
[ 64.169977] flags: 0x4000000000000000(zone=1)
[ 64.169977] raw: 4000000000000000 0000000000000000 ffffea0000387fc8 0000000000000000
[ 64.169977] raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
[ 64.169977] page dumped because: kasan: bad access detected
[ 64.169977] Memory state around the buggy address:
[ 64.169977] ffff88800e1ffc00: f2 f2 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00
[ 64.169977] ffff88800e1ffc80: 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00
[ 64.169977] >ffff88800e1ffd00: 00 00 00 00 f3 f3 f3 f3 f3 00 00 00 00 00 00 00
[ 64.169977] ^
[ 64.169977] ffff88800e1ffd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
[ 64.169977] ffff88800e1ffe00: f1 f1 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 64.169977] ==================================================================
[ 64.245153] Disabling lock debugging due to kernel taint
After the fix:
ip xfrm policy add src 10.1.1.1/32 dst 10.1.1.2/32 dir out tmpl \
src fc00::dead:1 dst fc00::dead:2 proto esp reqid 1 mode iptfs \
level use tmpl src fc00::dead:1 dst fc00::dead:2 proto esp reqid 2 \
mode transport
Error: Mode in optional template not allowed in outbound policy.
Fixes: d1716d5a44c3 ("xfrm: add generic iptfs defines and functionality")
Reported-by: syzbot+0ac4d84afe1066a1f3e9@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/6a3ceb94.43b4ff68.30a095.0004.GAE@google.com/T/ (local)
Signed-off-by: Antony Antony <redacted>
---
v1->v2: Fix Signed-off-by:
Link to v1: https://patch.msgid.link/20260625-xfrm-pol-out-tmpl-iptfs-reject-fix-v1-1-814861129086@secunet.com
---
net/xfrm/xfrm_user.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 6384795ee6b2..0f2c921b1e03 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c@@ -2104,13 +2104,12 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family, switch (ut[i].mode) { case XFRM_MODE_TUNNEL: case XFRM_MODE_BEET: + case XFRM_MODE_IPTFS: if (ut[i].optional && dir == XFRM_POLICY_OUT) { NL_SET_ERR_MSG(extack, "Mode in optional template not allowed in outbound policy"); return -EINVAL; } break; - case XFRM_MODE_IPTFS: - break; default: if (ut[i].family != prev_family) { NL_SET_ERR_MSG(extack, "Mode in template doesn't support a family change");
--- base-commit: 805185b7c7a1069e407b6f7b3bc98e44d415f484 change-id: 20260625-xfrm-pol-out-tmpl-iptfs-reject-fix-10373324a111 Best regards, -- Antony