Skip to content

Commit 291d5dc

Browse files
author
Paolo Abeni
committed
Merge tag 'ipsec-2025-07-23' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2025-07-23 1) Premption fixes for xfrm_state_find. From Sabrina Dubroca. 2) Initialize offload path also for SW IPsec GRO. This fixes a performance regression on SW IPsec offload. From Leon Romanovsky. 3) Fix IPsec UDP GRO for IKE packets. From Tobias Brunner, 4) Fix transport header setting for IPcomp after decompressing. From Fernando Fernandez Mancera. 5) Fix use-after-free when xfrmi_changelink tries to change collect_md for a xfrm interface. From Eyal Birger . 6) Delete the special IPcomp x->tunnel state along with the state x to avoid refcount problems. From Sabrina Dubroca. Please pull or let me know if there are problems. * tag 'ipsec-2025-07-23' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: Revert "xfrm: destroy xfrm_state synchronously on net exit path" xfrm: delete x->tunnel as we delete x xfrm: interface: fix use-after-free after changing collect_md xfrm interface xfrm: ipcomp: adjust transport header after decompressing xfrm: Set transport header to fix UDP GRO handling xfrm: always initialize offload path xfrm: state: use a consistent pcpu_id in xfrm_state_find xfrm: state: initialize state_ptrs earlier in xfrm_state_find ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 89fd905 + 28712d6 commit 291d5dc

File tree

12 files changed

+46
-66
lines changed

12 files changed

+46
-66
lines changed

include/net/xfrm.h

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,6 @@ int xfrm_input_register_afinfo(const struct xfrm_input_afinfo *afinfo);
441441
int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo);
442442

443443
void xfrm_flush_gc(void);
444-
void xfrm_state_delete_tunnel(struct xfrm_state *x);
445444

446445
struct xfrm_type {
447446
struct module *owner;
@@ -474,7 +473,7 @@ struct xfrm_type_offload {
474473

475474
int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family);
476475
void xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
477-
void xfrm_set_type_offload(struct xfrm_state *x);
476+
void xfrm_set_type_offload(struct xfrm_state *x, bool try_load);
478477
static inline void xfrm_unset_type_offload(struct xfrm_state *x)
479478
{
480479
if (!x->type_offload)
@@ -916,7 +915,7 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
916915
xfrm_pol_put(pols[i]);
917916
}
918917

919-
void __xfrm_state_destroy(struct xfrm_state *, bool);
918+
void __xfrm_state_destroy(struct xfrm_state *);
920919

921920
static inline void __xfrm_state_put(struct xfrm_state *x)
922921
{
@@ -926,13 +925,7 @@ static inline void __xfrm_state_put(struct xfrm_state *x)
926925
static inline void xfrm_state_put(struct xfrm_state *x)
927926
{
928927
if (refcount_dec_and_test(&x->refcnt))
929-
__xfrm_state_destroy(x, false);
930-
}
931-
932-
static inline void xfrm_state_put_sync(struct xfrm_state *x)
933-
{
934-
if (refcount_dec_and_test(&x->refcnt))
935-
__xfrm_state_destroy(x, true);
928+
__xfrm_state_destroy(x);
936929
}
937930

938931
static inline void xfrm_state_hold(struct xfrm_state *x)
@@ -1770,7 +1763,7 @@ struct xfrmk_spdinfo {
17701763

17711764
struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq, u32 pcpu_num);
17721765
int xfrm_state_delete(struct xfrm_state *x);
1773-
int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync);
1766+
int xfrm_state_flush(struct net *net, u8 proto, bool task_valid);
17741767
int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid);
17751768
int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
17761769
bool task_valid);

net/ipv4/ipcomp.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ static int ipcomp4_err(struct sk_buff *skb, u32 info)
5454
}
5555

5656
/* We always hold one tunnel user reference to indicate a tunnel */
57+
static struct lock_class_key xfrm_state_lock_key;
5758
static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
5859
{
5960
struct net *net = xs_net(x);
@@ -62,6 +63,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
6263
t = xfrm_state_alloc(net);
6364
if (!t)
6465
goto out;
66+
lockdep_set_class(&t->lock, &xfrm_state_lock_key);
6567

6668
t->id.proto = IPPROTO_IPIP;
6769
t->id.spi = x->props.saddr.a4;

net/ipv4/xfrm4_input.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ struct sk_buff *xfrm4_gro_udp_encap_rcv(struct sock *sk, struct list_head *head,
202202
if (len <= sizeof(struct ip_esp_hdr) || udpdata32[0] == 0)
203203
goto out;
204204

205+
/* set the transport header to ESP */
206+
skb_set_transport_header(skb, offset);
207+
205208
NAPI_GRO_CB(skb)->proto = IPPROTO_UDP;
206209

207210
pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);

net/ipv6/ipcomp6.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
7171
return 0;
7272
}
7373

74+
static struct lock_class_key xfrm_state_lock_key;
7475
static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
7576
{
7677
struct net *net = xs_net(x);
@@ -79,6 +80,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
7980
t = xfrm_state_alloc(net);
8081
if (!t)
8182
goto out;
83+
lockdep_set_class(&t->lock, &xfrm_state_lock_key);
8284

8385
t->id.proto = IPPROTO_IPV6;
8486
t->id.spi = xfrm6_tunnel_alloc_spi(net, (xfrm_address_t *)&x->props.saddr);

net/ipv6/xfrm6_input.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ struct sk_buff *xfrm6_gro_udp_encap_rcv(struct sock *sk, struct list_head *head,
202202
if (len <= sizeof(struct ip_esp_hdr) || udpdata32[0] == 0)
203203
goto out;
204204

205+
/* set the transport header to ESP */
206+
skb_set_transport_header(skb, offset);
207+
205208
NAPI_GRO_CB(skb)->proto = IPPROTO_UDP;
206209

207210
pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);

net/ipv6/xfrm6_tunnel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,8 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)
334334
struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
335335
unsigned int i;
336336

337+
xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
337338
xfrm_flush_gc();
338-
xfrm_state_flush(net, 0, false, true);
339339

340340
for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
341341
WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i]));

net/key/af_key.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1766,7 +1766,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, const struct sadb_m
17661766
if (proto == 0)
17671767
return -EINVAL;
17681768

1769-
err = xfrm_state_flush(net, proto, true, false);
1769+
err = xfrm_state_flush(net, proto, true);
17701770
err2 = unicast_flush_resp(sk, hdr);
17711771
if (err || err2) {
17721772
if (err == -ESRCH) /* empty table - go quietly */

net/xfrm/xfrm_device.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,6 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
305305
return -EINVAL;
306306
}
307307

308-
xfrm_set_type_offload(x);
309308
if (!x->type_offload) {
310309
NL_SET_ERR_MSG(extack, "Type doesn't support offload");
311310
dev_put(dev);

net/xfrm/xfrm_interface_core.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
875875
return -EINVAL;
876876
}
877877

878-
if (p.collect_md) {
878+
if (p.collect_md || xi->p.collect_md) {
879879
NL_SET_ERR_MSG(extack, "collect_md can't be changed");
880880
return -EINVAL;
881881
}
@@ -886,11 +886,6 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
886886
} else {
887887
if (xi->dev != dev)
888888
return -EEXIST;
889-
if (xi->p.collect_md) {
890-
NL_SET_ERR_MSG(extack,
891-
"device can't be changed to collect_md");
892-
return -EINVAL;
893-
}
894889
}
895890

896891
return xfrmi_update(xi, &p);

net/xfrm/xfrm_ipcomp.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ static int ipcomp_input_done2(struct sk_buff *skb, int err)
9797
struct ip_comp_hdr *ipch = ip_comp_hdr(skb);
9898
const int plen = skb->len;
9999

100-
skb_reset_transport_header(skb);
100+
skb->transport_header = skb->network_header + sizeof(*ipch);
101101

102102
return ipcomp_post_acomp(skb, err, 0) ?:
103103
skb->len < (plen + sizeof(ip_comp_hdr)) ? -EINVAL :
@@ -313,7 +313,6 @@ void ipcomp_destroy(struct xfrm_state *x)
313313
struct ipcomp_data *ipcd = x->data;
314314
if (!ipcd)
315315
return;
316-
xfrm_state_delete_tunnel(x);
317316
ipcomp_free_data(ipcd);
318317
kfree(ipcd);
319318
}

0 commit comments

Comments
 (0)