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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ipsec-2025-11-18' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2025-11-18

1) Misc fixes for xfrm_state creation/modification/deletion.
Patchset from Sabrina Dubroca.

2) Fix inner packet family determination for xfrm offloads.
From Jianbo Liu.

3) Don't push locally generated packets directly to L2 tunnel
mode offloading, they still need processing from the standard
xfrm path. From Jianbo Liu.

4) Fix memory leaks in xfrm_add_acquire for policy offloads and policy
security contexts. From Zilin Guan.

* tag 'ipsec-2025-11-18' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec:
xfrm: fix memory leak in xfrm_add_acquire()
xfrm: Prevent locally generated packets from direct output in tunnel mode
xfrm: Determine inner GSO type from packet inner protocol
xfrm: Check inner packet family directly from skb_dst
xfrm: check all hash buckets for leftover states during netns deletion
xfrm: set err and extack on failure to create pcpu SA
xfrm: call xfrm_dev_state_delete when xfrm_state_migrate fails to add the state
xfrm: make state as DEAD before final put when migrate fails
xfrm: also call xfrm_state_delete_tunnel at destroy time for states that were never added
xfrm: drop SA reference in xfrm_state_update if dir doesn't match
====================

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

+46 -17
+2 -1
include/net/xfrm.h
··· 536 536 537 537 static inline const struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto) 538 538 { 539 - if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) || 539 + if ((x->sel.family != AF_UNSPEC) || 540 + (ipproto == IPPROTO_IPIP && x->props.family == AF_INET) || 540 541 (ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6)) 541 542 return &x->inner_mode; 542 543 else
+4 -2
net/ipv4/esp4_offload.c
··· 122 122 struct sk_buff *skb, 123 123 netdev_features_t features) 124 124 { 125 - __be16 type = x->inner_mode.family == AF_INET6 ? htons(ETH_P_IPV6) 126 - : htons(ETH_P_IP); 125 + const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x, 126 + XFRM_MODE_SKB_CB(skb)->protocol); 127 + __be16 type = inner_mode->family == AF_INET6 ? htons(ETH_P_IPV6) 128 + : htons(ETH_P_IP); 127 129 128 130 return skb_eth_gso_segment(skb, features, type); 129 131 }
+4 -2
net/ipv6/esp6_offload.c
··· 158 158 struct sk_buff *skb, 159 159 netdev_features_t features) 160 160 { 161 - __be16 type = x->inner_mode.family == AF_INET ? htons(ETH_P_IP) 162 - : htons(ETH_P_IPV6); 161 + const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x, 162 + XFRM_MODE_SKB_CB(skb)->protocol); 163 + __be16 type = inner_mode->family == AF_INET ? htons(ETH_P_IP) 164 + : htons(ETH_P_IPV6); 163 165 164 166 return skb_eth_gso_segment(skb, features, type); 165 167 }
+1 -1
net/xfrm/xfrm_device.c
··· 438 438 439 439 check_tunnel_size = x->xso.type == XFRM_DEV_OFFLOAD_PACKET && 440 440 x->props.mode == XFRM_MODE_TUNNEL; 441 - switch (x->inner_mode.family) { 441 + switch (skb_dst(skb)->ops->family) { 442 442 case AF_INET: 443 443 /* Check for IPv4 options */ 444 444 if (ip_hdr(skb)->ihl != 5)
+6 -2
net/xfrm/xfrm_output.c
··· 698 698 return; 699 699 700 700 if (x->outer_mode.encap == XFRM_MODE_TUNNEL) { 701 - switch (x->outer_mode.family) { 701 + switch (skb_dst(skb)->ops->family) { 702 702 case AF_INET: 703 703 xo->inner_ipproto = ip_hdr(skb)->protocol; 704 704 break; ··· 772 772 /* Exclusive direct xmit for tunnel mode, as 773 773 * some filtering or matching rules may apply 774 774 * in transport mode. 775 + * Locally generated packets also require 776 + * the normal XFRM path for L2 header setup, 777 + * as the hardware needs the L2 header to match 778 + * for encryption, so skip direct output as well. 775 779 */ 776 - if (x->props.mode == XFRM_MODE_TUNNEL) 780 + if (x->props.mode == XFRM_MODE_TUNNEL && !skb->sk) 777 781 return xfrm_dev_direct_output(sk, x, skb); 778 782 779 783 return xfrm_output_resume(sk, skb, 0);
+22 -8
net/xfrm/xfrm_state.c
··· 592 592 } 593 593 EXPORT_SYMBOL(xfrm_state_free); 594 594 595 + static void xfrm_state_delete_tunnel(struct xfrm_state *x); 595 596 static void xfrm_state_gc_destroy(struct xfrm_state *x) 596 597 { 597 598 if (x->mode_cbs && x->mode_cbs->destroy_state) ··· 608 607 kfree(x->replay_esn); 609 608 kfree(x->preplay_esn); 610 609 xfrm_unset_type_offload(x); 610 + xfrm_state_delete_tunnel(x); 611 611 if (x->type) { 612 612 x->type->destructor(x); 613 613 xfrm_put_type(x->type); ··· 808 806 } 809 807 EXPORT_SYMBOL(__xfrm_state_destroy); 810 808 811 - static void xfrm_state_delete_tunnel(struct xfrm_state *x); 812 809 int __xfrm_state_delete(struct xfrm_state *x) 813 810 { 814 811 struct net *net = xs_net(x); ··· 2074 2073 return x; 2075 2074 2076 2075 error: 2076 + x->km.state = XFRM_STATE_DEAD; 2077 2077 xfrm_state_put(x); 2078 2078 out: 2079 2079 return NULL; ··· 2159 2157 xfrm_state_insert(xc); 2160 2158 } else { 2161 2159 if (xfrm_state_add(xc) < 0) 2162 - goto error; 2160 + goto error_add; 2163 2161 } 2164 2162 2165 2163 return xc; 2164 + error_add: 2165 + if (xuo) 2166 + xfrm_dev_state_delete(xc); 2166 2167 error: 2168 + xc->km.state = XFRM_STATE_DEAD; 2167 2169 xfrm_state_put(xc); 2168 2170 return NULL; 2169 2171 } ··· 2197 2191 } 2198 2192 2199 2193 if (x1->km.state == XFRM_STATE_ACQ) { 2200 - if (x->dir && x1->dir != x->dir) 2194 + if (x->dir && x1->dir != x->dir) { 2195 + to_put = x1; 2201 2196 goto out; 2197 + } 2202 2198 2203 2199 __xfrm_state_insert(x); 2204 2200 x = NULL; 2205 2201 } else { 2206 - if (x1->dir != x->dir) 2202 + if (x1->dir != x->dir) { 2203 + to_put = x1; 2207 2204 goto out; 2205 + } 2208 2206 } 2209 2207 err = 0; 2210 2208 ··· 3308 3298 void xfrm_state_fini(struct net *net) 3309 3299 { 3310 3300 unsigned int sz; 3301 + int i; 3311 3302 3312 3303 flush_work(&net->xfrm.state_hash_work); 3313 3304 xfrm_state_flush(net, 0, false); ··· 3316 3305 3317 3306 WARN_ON(!list_empty(&net->xfrm.state_all)); 3318 3307 3308 + for (i = 0; i <= net->xfrm.state_hmask; i++) { 3309 + WARN_ON(!hlist_empty(net->xfrm.state_byseq + i)); 3310 + WARN_ON(!hlist_empty(net->xfrm.state_byspi + i)); 3311 + WARN_ON(!hlist_empty(net->xfrm.state_bysrc + i)); 3312 + WARN_ON(!hlist_empty(net->xfrm.state_bydst + i)); 3313 + } 3314 + 3319 3315 sz = (net->xfrm.state_hmask + 1) * sizeof(struct hlist_head); 3320 - WARN_ON(!hlist_empty(net->xfrm.state_byseq)); 3321 3316 xfrm_hash_free(net->xfrm.state_byseq, sz); 3322 - WARN_ON(!hlist_empty(net->xfrm.state_byspi)); 3323 3317 xfrm_hash_free(net->xfrm.state_byspi, sz); 3324 - WARN_ON(!hlist_empty(net->xfrm.state_bysrc)); 3325 3318 xfrm_hash_free(net->xfrm.state_bysrc, sz); 3326 - WARN_ON(!hlist_empty(net->xfrm.state_bydst)); 3327 3319 xfrm_hash_free(net->xfrm.state_bydst, sz); 3328 3320 free_percpu(net->xfrm.state_cache_input); 3329 3321 }
+7 -1
net/xfrm/xfrm_user.c
··· 947 947 948 948 if (attrs[XFRMA_SA_PCPU]) { 949 949 x->pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]); 950 - if (x->pcpu_num >= num_possible_cpus()) 950 + if (x->pcpu_num >= num_possible_cpus()) { 951 + err = -ERANGE; 952 + NL_SET_ERR_MSG(extack, "pCPU number too big"); 951 953 goto error; 954 + } 952 955 } 953 956 954 957 err = __xfrm_init_state(x, extack); ··· 3038 3035 } 3039 3036 3040 3037 xfrm_state_free(x); 3038 + xfrm_dev_policy_delete(xp); 3039 + xfrm_dev_policy_free(xp); 3040 + security_xfrm_policy_free(xp->security); 3041 3041 kfree(xp); 3042 3042 3043 3043 return 0;