summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-02-20 15:57:55 -0800
committerJakub Kicinski <kuba@kernel.org>2026-02-20 15:57:55 -0800
commit0aebd81fa8aef55001467e61660fe0c0f8d1cee8 (patch)
tree439f219d6cf82b887983eda4598dff3c7a05aa9b /net
parent9b8eeccd7110d10f9c1b1aa456f5efac23e4e383 (diff)
parent4efa91a28576054aae0e6dad9cba8fed8293aef8 (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/xfrm6_policy.c7
-rw-r--r--net/xfrm/xfrm_device.c12
-rw-r--r--net/xfrm/xfrm_policy.c11
3 files changed, 25 insertions, 5 deletions
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 1f19b6f14484..125ea9a5b8a0 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -57,6 +57,7 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr,
struct dst_entry *dst;
struct net_device *dev;
struct inet6_dev *idev;
+ int err;
dst = xfrm6_dst_lookup(params);
if (IS_ERR(dst))
@@ -68,9 +69,11 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr,
return -EHOSTUNREACH;
}
dev = idev->dev;
- ipv6_dev_get_saddr(dev_net(dev), dev, &params->daddr->in6, 0,
- &saddr->in6);
+ err = ipv6_dev_get_saddr(dev_net(dev), dev, &params->daddr->in6, 0,
+ &saddr->in6);
dst_release(dst);
+ if (err)
+ return -EHOSTUNREACH;
return 0;
}
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 52ae0e034d29..550457e4c4f0 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -544,6 +544,14 @@ static int xfrm_dev_down(struct net_device *dev)
return NOTIFY_DONE;
}
+static int xfrm_dev_unregister(struct net_device *dev)
+{
+ xfrm_dev_state_flush(dev_net(dev), dev, true);
+ xfrm_dev_policy_flush(dev_net(dev), dev, true);
+
+ return NOTIFY_DONE;
+}
+
static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
@@ -556,8 +564,10 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
return xfrm_api_check(dev);
case NETDEV_DOWN:
- case NETDEV_UNREGISTER:
return xfrm_dev_down(dev);
+
+ case NETDEV_UNREGISTER:
+ return xfrm_dev_unregister(dev);
}
return NOTIFY_DONE;
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 62486f866975..5428185196a1 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3801,8 +3801,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
struct xfrm_tmpl *tp[XFRM_MAX_DEPTH];
struct xfrm_tmpl *stp[XFRM_MAX_DEPTH];
struct xfrm_tmpl **tpp = tp;
+ int i, k = 0;
int ti = 0;
- int i, k;
sp = skb_sec_path(skb);
if (!sp)
@@ -3828,6 +3828,12 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
tpp = stp;
}
+ if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET && sp == &dummy)
+ /* This policy template was already checked by HW
+ * and secpath was removed in __xfrm_policy_check2.
+ */
+ goto out;
+
/* For each tunnel xfrm, find the first matching tmpl.
* For each tmpl before that, find corresponding xfrm.
* Order is _important_. Later we will implement
@@ -3837,7 +3843,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
* verified to allow them to be skipped in future policy
* checks (e.g. nested tunnels).
*/
- for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
+ for (i = xfrm_nr - 1; i >= 0; i--) {
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
if (k < 0) {
if (k < -1)
@@ -3853,6 +3859,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
goto reject;
}
+out:
xfrm_pols_put(pols, npols);
sp->verified_cnt = k;