Skip to content

Commit 51a209e

Browse files
author
Paolo Abeni
committed
Merge tag 'ipsec-2026-03-23' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2026-03-23 1) Add missing extack for XFRMA_SA_PCPU in add_acquire and allocspi. From Sabrina Dubroca. 2) Fix the condition on x->pcpu_num in xfrm_sa_len by using the proper check. From Sabrina Dubroca. 3) Call xdo_dev_state_delete during state update to properly cleanup the xdo device state. From Sabrina Dubroca. 4) Fix a potential skb leak in espintcp when async crypto is used. From Sabrina Dubroca. 5) Validate inner IPv4 header length in IPTFS payload to avoid parsing malformed packets. From Roshan Kumar. 6) Fix skb_put() panic on non-linear skb during IPTFS reassembly. From Fernando Fernandez Mancera. 7) Silence various sparse warnings related to RCU, state, and policy handling. From Sabrina Dubroca. 8) Fix work re-schedule race after cancel in xfrm_nat_keepalive_net_fini(). From Hyunwoo Kim. 9) Prevent policy_hthresh.work from racing with netns teardown by using a proper cleanup mechanism. From Minwoo Ra. 10) Validate that the family of the source and destination addresses match in pfkey_send_migrate(). From Eric Dumazet. 11) Only publish mode_data after the clone is setup in the IPTFS receive path. This prevents leaving x->mode_data pointing at freed memory on error. From Paul Moses. Please pull or let me know if there are problems. ipsec-2026-03-23 * tag 'ipsec-2026-03-23' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm: iptfs: only publish mode_data after clone setup af_key: validate families in pfkey_send_migrate() xfrm: prevent policy_hthresh.work from racing with netns teardown xfrm: Fix work re-schedule after cancel in xfrm_nat_keepalive_net_fini() xfrm: avoid RCU warnings around the per-netns netlink socket xfrm: add rcu_access_pointer to silence sparse warning for xfrm_input_afinfo xfrm: policy: silence sparse warning in xfrm_policy_unregister_afinfo xfrm: policy: fix sparse warnings in xfrm_policy_{init,fini} xfrm: state: silence sparse warnings during netns exit xfrm: remove rcu/state_hold from xfrm_state_lookup_spi_proto xfrm: state: add xfrm_state_deref_prot to state_by* walk under lock xfrm: state: fix sparse warnings around XFRM_STATE_INSERT xfrm: state: fix sparse warnings in xfrm_state_init xfrm: state: fix sparse warnings on xfrm_state_hold_rcu xfrm: iptfs: fix skb_put() panic on non-linear skb during reassembly xfrm: iptfs: validate inner IPv4 header length in IPTFS payload esp: fix skb leak with espintcp and async crypto xfrm: call xdo_dev_state_delete during state update xfrm: fix the condition on x->pcpu_num in xfrm_sa_len xfrm: add missing extack for XFRMA_SA_PCPU in add_acquire and allocspi ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 647b8a2 + d849a2f commit 51a209e

10 files changed

Lines changed: 137 additions & 86 deletions

File tree

include/net/netns/xfrm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ struct netns_xfrm {
5959
struct list_head inexact_bins;
6060

6161

62-
struct sock *nlsk;
62+
struct sock __rcu *nlsk;
6363
struct sock *nlsk_stash;
6464

6565
u32 sysctl_aevent_etime;

net/ipv4/esp4.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,13 @@ static void esp_output_done(void *data, int err)
235235
xfrm_dev_resume(skb);
236236
} else {
237237
if (!err &&
238-
x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
239-
esp_output_tail_tcp(x, skb);
240-
else
238+
x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) {
239+
err = esp_output_tail_tcp(x, skb);
240+
if (err != -EINPROGRESS)
241+
kfree_skb(skb);
242+
} else {
241243
xfrm_output_resume(skb_to_full_sk(skb), skb, err);
244+
}
242245
}
243246
}
244247

net/ipv6/esp6.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,13 @@ static void esp_output_done(void *data, int err)
271271
xfrm_dev_resume(skb);
272272
} else {
273273
if (!err &&
274-
x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
275-
esp_output_tail_tcp(x, skb);
276-
else
274+
x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) {
275+
err = esp_output_tail_tcp(x, skb);
276+
if (err != -EINPROGRESS)
277+
kfree_skb(skb);
278+
} else {
277279
xfrm_output_resume(skb_to_full_sk(skb), skb, err);
280+
}
278281
}
279282
}
280283

net/key/af_key.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3518,7 +3518,7 @@ static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress *
35183518

35193519
static int set_ipsecrequest(struct sk_buff *skb,
35203520
uint8_t proto, uint8_t mode, int level,
3521-
uint32_t reqid, uint8_t family,
3521+
uint32_t reqid, sa_family_t family,
35223522
const xfrm_address_t *src, const xfrm_address_t *dst)
35233523
{
35243524
struct sadb_x_ipsecrequest *rq;
@@ -3583,12 +3583,17 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
35833583

35843584
/* ipsecrequests */
35853585
for (i = 0, mp = m; i < num_bundles; i++, mp++) {
3586-
/* old locator pair */
3587-
size_pol += sizeof(struct sadb_x_ipsecrequest) +
3588-
pfkey_sockaddr_pair_size(mp->old_family);
3589-
/* new locator pair */
3590-
size_pol += sizeof(struct sadb_x_ipsecrequest) +
3591-
pfkey_sockaddr_pair_size(mp->new_family);
3586+
int pair_size;
3587+
3588+
pair_size = pfkey_sockaddr_pair_size(mp->old_family);
3589+
if (!pair_size)
3590+
return -EINVAL;
3591+
size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size;
3592+
3593+
pair_size = pfkey_sockaddr_pair_size(mp->new_family);
3594+
if (!pair_size)
3595+
return -EINVAL;
3596+
size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size;
35923597
}
35933598

35943599
size += sizeof(struct sadb_msg) + size_pol;

net/xfrm/xfrm_input.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo)
7575

7676
spin_lock_bh(&xfrm_input_afinfo_lock);
7777
if (likely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family])) {
78-
if (unlikely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family] != afinfo))
78+
const struct xfrm_input_afinfo *cur;
79+
80+
cur = rcu_access_pointer(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family]);
81+
if (unlikely(cur != afinfo))
7982
err = -EINVAL;
8083
else
8184
RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family], NULL);

net/xfrm/xfrm_iptfs.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,12 @@ static u32 iptfs_reassem_cont(struct xfrm_iptfs_data *xtfs, u64 seq,
901901
iptfs_skb_can_add_frags(newskb, fragwalk, data, copylen)) {
902902
iptfs_skb_add_frags(newskb, fragwalk, data, copylen);
903903
} else {
904+
if (skb_linearize(newskb)) {
905+
XFRM_INC_STATS(xs_net(xtfs->x),
906+
LINUX_MIB_XFRMINBUFFERERROR);
907+
goto abandon;
908+
}
909+
904910
/* copy fragment data into newskb */
905911
if (skb_copy_seq_read(st, data, skb_put(newskb, copylen),
906912
copylen)) {
@@ -991,6 +997,11 @@ static bool __input_process_payload(struct xfrm_state *x, u32 data,
991997

992998
iplen = be16_to_cpu(iph->tot_len);
993999
iphlen = iph->ihl << 2;
1000+
if (iplen < iphlen || iphlen < sizeof(*iph)) {
1001+
XFRM_INC_STATS(net,
1002+
LINUX_MIB_XFRMINHDRERROR);
1003+
goto done;
1004+
}
9941005
protocol = cpu_to_be16(ETH_P_IP);
9951006
XFRM_MODE_SKB_CB(skbseq->root_skb)->tos = iph->tos;
9961007
} else if (iph->version == 0x6) {
@@ -2653,9 +2664,6 @@ static int iptfs_clone_state(struct xfrm_state *x, struct xfrm_state *orig)
26532664
if (!xtfs)
26542665
return -ENOMEM;
26552666

2656-
x->mode_data = xtfs;
2657-
xtfs->x = x;
2658-
26592667
xtfs->ra_newskb = NULL;
26602668
if (xtfs->cfg.reorder_win_size) {
26612669
xtfs->w_saved = kzalloc_objs(*xtfs->w_saved,
@@ -2666,6 +2674,9 @@ static int iptfs_clone_state(struct xfrm_state *x, struct xfrm_state *orig)
26662674
}
26672675
}
26682676

2677+
x->mode_data = xtfs;
2678+
xtfs->x = x;
2679+
26692680
return 0;
26702681
}
26712682

net/xfrm/xfrm_nat_keepalive.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ int __net_init xfrm_nat_keepalive_net_init(struct net *net)
261261

262262
int xfrm_nat_keepalive_net_fini(struct net *net)
263263
{
264-
cancel_delayed_work_sync(&net->xfrm.nat_keepalive_work);
264+
disable_delayed_work_sync(&net->xfrm.nat_keepalive_work);
265265
return 0;
266266
}
267267

net/xfrm/xfrm_policy.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4156,7 +4156,7 @@ void xfrm_policy_unregister_afinfo(const struct xfrm_policy_afinfo *afinfo)
41564156
int i;
41574157

41584158
for (i = 0; i < ARRAY_SIZE(xfrm_policy_afinfo); i++) {
4159-
if (xfrm_policy_afinfo[i] != afinfo)
4159+
if (rcu_access_pointer(xfrm_policy_afinfo[i]) != afinfo)
41604160
continue;
41614161
RCU_INIT_POINTER(xfrm_policy_afinfo[i], NULL);
41624162
break;
@@ -4242,7 +4242,7 @@ static int __net_init xfrm_policy_init(struct net *net)
42424242
net->xfrm.policy_count[XFRM_POLICY_MAX + dir] = 0;
42434243

42444244
htab = &net->xfrm.policy_bydst[dir];
4245-
htab->table = xfrm_hash_alloc(sz);
4245+
rcu_assign_pointer(htab->table, xfrm_hash_alloc(sz));
42464246
if (!htab->table)
42474247
goto out_bydst;
42484248
htab->hmask = hmask;
@@ -4269,7 +4269,7 @@ static int __net_init xfrm_policy_init(struct net *net)
42694269
struct xfrm_policy_hash *htab;
42704270

42714271
htab = &net->xfrm.policy_bydst[dir];
4272-
xfrm_hash_free(htab->table, sz);
4272+
xfrm_hash_free(rcu_dereference_protected(htab->table, true), sz);
42734273
}
42744274
xfrm_hash_free(net->xfrm.policy_byidx, sz);
42754275
out_byidx:
@@ -4282,6 +4282,8 @@ static void xfrm_policy_fini(struct net *net)
42824282
unsigned int sz;
42834283
int dir;
42844284

4285+
disable_work_sync(&net->xfrm.policy_hthresh.work);
4286+
42854287
flush_work(&net->xfrm.policy_hash_work);
42864288
#ifdef CONFIG_XFRM_SUB_POLICY
42874289
xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, false);
@@ -4295,8 +4297,8 @@ static void xfrm_policy_fini(struct net *net)
42954297

42964298
htab = &net->xfrm.policy_bydst[dir];
42974299
sz = (htab->hmask + 1) * sizeof(struct hlist_head);
4298-
WARN_ON(!hlist_empty(htab->table));
4299-
xfrm_hash_free(htab->table, sz);
4300+
WARN_ON(!hlist_empty(rcu_dereference_protected(htab->table, true)));
4301+
xfrm_hash_free(rcu_dereference_protected(htab->table, true), sz);
43004302
}
43014303

43024304
sz = (net->xfrm.policy_idx_hmask + 1) * sizeof(struct hlist_head);

0 commit comments

Comments
 (0)