Commit c3995fc1 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
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: default avatarJakub Kicinski <kuba@kernel.org>
parents f94c1a11 a55ef3bf
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -536,7 +536,8 @@ static inline int xfrm_af2proto(unsigned int family)

static inline const struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto)
{
	if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
	if ((x->sel.family != AF_UNSPEC) ||
	    (ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
	    (ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6))
		return &x->inner_mode;
	else
+4 −2
Original line number Diff line number Diff line
@@ -122,7 +122,9 @@ static struct sk_buff *xfrm4_tunnel_gso_segment(struct xfrm_state *x,
						struct sk_buff *skb,
						netdev_features_t features)
{
	__be16 type = x->inner_mode.family == AF_INET6 ? htons(ETH_P_IPV6)
	const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x,
					XFRM_MODE_SKB_CB(skb)->protocol);
	__be16 type = inner_mode->family == AF_INET6 ? htons(ETH_P_IPV6)
						     : htons(ETH_P_IP);

	return skb_eth_gso_segment(skb, features, type);
+4 −2
Original line number Diff line number Diff line
@@ -158,7 +158,9 @@ static struct sk_buff *xfrm6_tunnel_gso_segment(struct xfrm_state *x,
						struct sk_buff *skb,
						netdev_features_t features)
{
	__be16 type = x->inner_mode.family == AF_INET ? htons(ETH_P_IP)
	const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x,
					XFRM_MODE_SKB_CB(skb)->protocol);
	__be16 type = inner_mode->family == AF_INET ? htons(ETH_P_IP)
						    : htons(ETH_P_IPV6);

	return skb_eth_gso_segment(skb, features, type);
+1 −1
Original line number Diff line number Diff line
@@ -438,7 +438,7 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)

	check_tunnel_size = x->xso.type == XFRM_DEV_OFFLOAD_PACKET &&
			    x->props.mode == XFRM_MODE_TUNNEL;
	switch (x->inner_mode.family) {
	switch (skb_dst(skb)->ops->family) {
	case AF_INET:
		/* Check for IPv4 options */
		if (ip_hdr(skb)->ihl != 5)
+6 −2
Original line number Diff line number Diff line
@@ -698,7 +698,7 @@ static void xfrm_get_inner_ipproto(struct sk_buff *skb, struct xfrm_state *x)
		return;

	if (x->outer_mode.encap == XFRM_MODE_TUNNEL) {
		switch (x->outer_mode.family) {
		switch (skb_dst(skb)->ops->family) {
		case AF_INET:
			xo->inner_ipproto = ip_hdr(skb)->protocol;
			break;
@@ -772,8 +772,12 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
		/* Exclusive direct xmit for tunnel mode, as
		 * some filtering or matching rules may apply
		 * in transport mode.
		 * Locally generated packets also require
		 * the normal XFRM path for L2 header setup,
		 * as the hardware needs the L2 header to match
		 * for encryption, so skip direct output as well.
		 */
		if (x->props.mode == XFRM_MODE_TUNNEL)
		if (x->props.mode == XFRM_MODE_TUNNEL && !skb->sk)
			return xfrm_dev_direct_output(sk, x, skb);

		return xfrm_output_resume(sk, skb, 0);
Loading