Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'ipsec-2026-02-20' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2026-02-20

1) Check the value of ipv6_dev_get_saddr() to fix an
uninitialized saddr in xfrm6_get_saddr().
From Jiayuan Chen.

2) Skip the templates check for packet offload in tunnel
mode. Is was already done by the hardware and causes
an unexpected XfrmInTmplMismatch increase.
From Leon Romanovsky.

3) Fix a unregister_netdevice stall due to not dropped
refcounts by always flushing xfrm state and policy
on a NETDEV_UNREGISTER event.
From Tetsuo Handa.

* tag 'ipsec-2026-02-20' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec:
xfrm: always flush state and policy upon NETDEV_UNREGISTER event
xfrm: skip templates check for packet offload tunnel mode
xfrm6: fix uninitialized saddr in xfrm6_get_saddr()
====================

Link: https://patch.msgid.link/20260220094133.14219-1-steffen.klassert@secunet.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+25 -5
+5 -2
net/ipv6/xfrm6_policy.c
··· 57 57 struct dst_entry *dst; 58 58 struct net_device *dev; 59 59 struct inet6_dev *idev; 60 + int err; 60 61 61 62 dst = xfrm6_dst_lookup(params); 62 63 if (IS_ERR(dst)) ··· 69 68 return -EHOSTUNREACH; 70 69 } 71 70 dev = idev->dev; 72 - ipv6_dev_get_saddr(dev_net(dev), dev, &params->daddr->in6, 0, 73 - &saddr->in6); 71 + err = ipv6_dev_get_saddr(dev_net(dev), dev, &params->daddr->in6, 0, 72 + &saddr->in6); 74 73 dst_release(dst); 74 + if (err) 75 + return -EHOSTUNREACH; 75 76 return 0; 76 77 } 77 78
+11 -1
net/xfrm/xfrm_device.c
··· 544 544 return NOTIFY_DONE; 545 545 } 546 546 547 + static int xfrm_dev_unregister(struct net_device *dev) 548 + { 549 + xfrm_dev_state_flush(dev_net(dev), dev, true); 550 + xfrm_dev_policy_flush(dev_net(dev), dev, true); 551 + 552 + return NOTIFY_DONE; 553 + } 554 + 547 555 static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) 548 556 { 549 557 struct net_device *dev = netdev_notifier_info_to_dev(ptr); ··· 564 556 return xfrm_api_check(dev); 565 557 566 558 case NETDEV_DOWN: 567 - case NETDEV_UNREGISTER: 568 559 return xfrm_dev_down(dev); 560 + 561 + case NETDEV_UNREGISTER: 562 + return xfrm_dev_unregister(dev); 569 563 } 570 564 return NOTIFY_DONE; 571 565 }
+9 -2
net/xfrm/xfrm_policy.c
··· 3801 3801 struct xfrm_tmpl *tp[XFRM_MAX_DEPTH]; 3802 3802 struct xfrm_tmpl *stp[XFRM_MAX_DEPTH]; 3803 3803 struct xfrm_tmpl **tpp = tp; 3804 + int i, k = 0; 3804 3805 int ti = 0; 3805 - int i, k; 3806 3806 3807 3807 sp = skb_sec_path(skb); 3808 3808 if (!sp) ··· 3828 3828 tpp = stp; 3829 3829 } 3830 3830 3831 + if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET && sp == &dummy) 3832 + /* This policy template was already checked by HW 3833 + * and secpath was removed in __xfrm_policy_check2. 3834 + */ 3835 + goto out; 3836 + 3831 3837 /* For each tunnel xfrm, find the first matching tmpl. 3832 3838 * For each tmpl before that, find corresponding xfrm. 3833 3839 * Order is _important_. Later we will implement ··· 3843 3837 * verified to allow them to be skipped in future policy 3844 3838 * checks (e.g. nested tunnels). 3845 3839 */ 3846 - for (i = xfrm_nr-1, k = 0; i >= 0; i--) { 3840 + for (i = xfrm_nr - 1; i >= 0; i--) { 3847 3841 k = xfrm_policy_ok(tpp[i], sp, k, family, if_id); 3848 3842 if (k < 0) { 3849 3843 if (k < -1) ··· 3859 3853 goto reject; 3860 3854 } 3861 3855 3856 + out: 3862 3857 xfrm_pols_put(pols, npols); 3863 3858 sp->verified_cnt = k; 3864 3859