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-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/20260323083440.2741292-1-steffen.klassert@secunet.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+137 -86
+1 -1
include/net/netns/xfrm.h
··· 59 59 struct list_head inexact_bins; 60 60 61 61 62 - struct sock *nlsk; 62 + struct sock __rcu *nlsk; 63 63 struct sock *nlsk_stash; 64 64 65 65 u32 sysctl_aevent_etime;
+6 -3
net/ipv4/esp4.c
··· 235 235 xfrm_dev_resume(skb); 236 236 } else { 237 237 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 { 241 243 xfrm_output_resume(skb_to_full_sk(skb), skb, err); 244 + } 242 245 } 243 246 } 244 247
+6 -3
net/ipv6/esp6.c
··· 271 271 xfrm_dev_resume(skb); 272 272 } else { 273 273 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 { 277 279 xfrm_output_resume(skb_to_full_sk(skb), skb, err); 280 + } 278 281 } 279 282 } 280 283
+12 -7
net/key/af_key.c
··· 3518 3518 3519 3519 static int set_ipsecrequest(struct sk_buff *skb, 3520 3520 uint8_t proto, uint8_t mode, int level, 3521 - uint32_t reqid, uint8_t family, 3521 + uint32_t reqid, sa_family_t family, 3522 3522 const xfrm_address_t *src, const xfrm_address_t *dst) 3523 3523 { 3524 3524 struct sadb_x_ipsecrequest *rq; ··· 3583 3583 3584 3584 /* ipsecrequests */ 3585 3585 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; 3592 3597 } 3593 3598 3594 3599 size += sizeof(struct sadb_msg) + size_pol;
+4 -1
net/xfrm/xfrm_input.c
··· 75 75 76 76 spin_lock_bh(&xfrm_input_afinfo_lock); 77 77 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)) 79 82 err = -EINVAL; 80 83 else 81 84 RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family], NULL);
+14 -3
net/xfrm/xfrm_iptfs.c
··· 901 901 iptfs_skb_can_add_frags(newskb, fragwalk, data, copylen)) { 902 902 iptfs_skb_add_frags(newskb, fragwalk, data, copylen); 903 903 } else { 904 + if (skb_linearize(newskb)) { 905 + XFRM_INC_STATS(xs_net(xtfs->x), 906 + LINUX_MIB_XFRMINBUFFERERROR); 907 + goto abandon; 908 + } 909 + 904 910 /* copy fragment data into newskb */ 905 911 if (skb_copy_seq_read(st, data, skb_put(newskb, copylen), 906 912 copylen)) { ··· 997 991 998 992 iplen = be16_to_cpu(iph->tot_len); 999 993 iphlen = iph->ihl << 2; 994 + if (iplen < iphlen || iphlen < sizeof(*iph)) { 995 + XFRM_INC_STATS(net, 996 + LINUX_MIB_XFRMINHDRERROR); 997 + goto done; 998 + } 1000 999 protocol = cpu_to_be16(ETH_P_IP); 1001 1000 XFRM_MODE_SKB_CB(skbseq->root_skb)->tos = iph->tos; 1002 1001 } else if (iph->version == 0x6) { ··· 2664 2653 if (!xtfs) 2665 2654 return -ENOMEM; 2666 2655 2667 - x->mode_data = xtfs; 2668 - xtfs->x = x; 2669 - 2670 2656 xtfs->ra_newskb = NULL; 2671 2657 if (xtfs->cfg.reorder_win_size) { 2672 2658 xtfs->w_saved = kzalloc_objs(*xtfs->w_saved, ··· 2673 2665 return -ENOMEM; 2674 2666 } 2675 2667 } 2668 + 2669 + x->mode_data = xtfs; 2670 + xtfs->x = x; 2676 2671 2677 2672 return 0; 2678 2673 }
+1 -1
net/xfrm/xfrm_nat_keepalive.c
··· 261 261 262 262 int xfrm_nat_keepalive_net_fini(struct net *net) 263 263 { 264 - cancel_delayed_work_sync(&net->xfrm.nat_keepalive_work); 264 + disable_delayed_work_sync(&net->xfrm.nat_keepalive_work); 265 265 return 0; 266 266 } 267 267
+7 -5
net/xfrm/xfrm_policy.c
··· 4156 4156 int i; 4157 4157 4158 4158 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) 4160 4160 continue; 4161 4161 RCU_INIT_POINTER(xfrm_policy_afinfo[i], NULL); 4162 4162 break; ··· 4242 4242 net->xfrm.policy_count[XFRM_POLICY_MAX + dir] = 0; 4243 4243 4244 4244 htab = &net->xfrm.policy_bydst[dir]; 4245 - htab->table = xfrm_hash_alloc(sz); 4245 + rcu_assign_pointer(htab->table, xfrm_hash_alloc(sz)); 4246 4246 if (!htab->table) 4247 4247 goto out_bydst; 4248 4248 htab->hmask = hmask; ··· 4269 4269 struct xfrm_policy_hash *htab; 4270 4270 4271 4271 htab = &net->xfrm.policy_bydst[dir]; 4272 - xfrm_hash_free(htab->table, sz); 4272 + xfrm_hash_free(rcu_dereference_protected(htab->table, true), sz); 4273 4273 } 4274 4274 xfrm_hash_free(net->xfrm.policy_byidx, sz); 4275 4275 out_byidx: ··· 4281 4281 struct xfrm_pol_inexact_bin *b, *t; 4282 4282 unsigned int sz; 4283 4283 int dir; 4284 + 4285 + disable_work_sync(&net->xfrm.policy_hthresh.work); 4284 4286 4285 4287 flush_work(&net->xfrm.policy_hash_work); 4286 4288 #ifdef CONFIG_XFRM_SUB_POLICY ··· 4297 4295 4298 4296 htab = &net->xfrm.policy_bydst[dir]; 4299 4297 sz = (htab->hmask + 1) * sizeof(struct hlist_head); 4300 - WARN_ON(!hlist_empty(htab->table)); 4301 - xfrm_hash_free(htab->table, sz); 4298 + WARN_ON(!hlist_empty(rcu_dereference_protected(htab->table, true))); 4299 + xfrm_hash_free(rcu_dereference_protected(htab->table, true), sz); 4302 4300 } 4303 4301 4304 4302 sz = (net->xfrm.policy_idx_hmask + 1) * sizeof(struct hlist_head);
+64 -52
net/xfrm/xfrm_state.c
··· 53 53 static HLIST_HEAD(xfrm_state_gc_list); 54 54 static HLIST_HEAD(xfrm_state_dev_gc_list); 55 55 56 - static inline bool xfrm_state_hold_rcu(struct xfrm_state __rcu *x) 56 + static inline bool xfrm_state_hold_rcu(struct xfrm_state *x) 57 57 { 58 58 return refcount_inc_not_zero(&x->refcnt); 59 59 } ··· 870 870 for (i = 0; i <= net->xfrm.state_hmask; i++) { 871 871 struct xfrm_state *x; 872 872 873 - hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) { 873 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bydst, net) + i, bydst) { 874 874 if (xfrm_id_proto_match(x->id.proto, proto) && 875 875 (err = security_xfrm_state_delete(x)) != 0) { 876 876 xfrm_audit_state_delete(x, 0, task_valid); ··· 891 891 struct xfrm_state *x; 892 892 struct xfrm_dev_offload *xso; 893 893 894 - hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) { 894 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bydst, net) + i, bydst) { 895 895 xso = &x->xso; 896 896 897 897 if (xso->dev == dev && ··· 931 931 for (i = 0; i <= net->xfrm.state_hmask; i++) { 932 932 struct xfrm_state *x; 933 933 restart: 934 - hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) { 934 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bydst, net) + i, bydst) { 935 935 if (!xfrm_state_kern(x) && 936 936 xfrm_id_proto_match(x->id.proto, proto)) { 937 937 xfrm_state_hold(x); ··· 973 973 err = -ESRCH; 974 974 for (i = 0; i <= net->xfrm.state_hmask; i++) { 975 975 restart: 976 - hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) { 976 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bydst, net) + i, bydst) { 977 977 xso = &x->xso; 978 978 979 979 if (!xfrm_state_kern(x) && xso->dev == dev) { ··· 1563 1563 list_add(&x->km.all, &net->xfrm.state_all); 1564 1564 h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family); 1565 1565 XFRM_STATE_INSERT(bydst, &x->bydst, 1566 - net->xfrm.state_bydst + h, 1566 + xfrm_state_deref_prot(net->xfrm.state_bydst, net) + h, 1567 1567 x->xso.type); 1568 1568 h = xfrm_src_hash(net, daddr, saddr, encap_family); 1569 1569 XFRM_STATE_INSERT(bysrc, &x->bysrc, 1570 - net->xfrm.state_bysrc + h, 1570 + xfrm_state_deref_prot(net->xfrm.state_bysrc, net) + h, 1571 1571 x->xso.type); 1572 1572 INIT_HLIST_NODE(&x->state_cache); 1573 1573 if (x->id.spi) { 1574 1574 h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, encap_family); 1575 1575 XFRM_STATE_INSERT(byspi, &x->byspi, 1576 - net->xfrm.state_byspi + h, 1576 + xfrm_state_deref_prot(net->xfrm.state_byspi, net) + h, 1577 1577 x->xso.type); 1578 1578 } 1579 1579 if (x->km.seq) { 1580 1580 h = xfrm_seq_hash(net, x->km.seq); 1581 1581 XFRM_STATE_INSERT(byseq, &x->byseq, 1582 - net->xfrm.state_byseq + h, 1582 + xfrm_state_deref_prot(net->xfrm.state_byseq, net) + h, 1583 1583 x->xso.type); 1584 1584 } 1585 1585 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; ··· 1652 1652 1653 1653 spin_lock_bh(&net->xfrm.xfrm_state_lock); 1654 1654 h = xfrm_dst_hash(net, daddr, saddr, reqid, family); 1655 - hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) { 1655 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bydst, net) + h, bydst) { 1656 1656 if (x->props.family == family && 1657 1657 x->props.reqid == reqid && 1658 1658 (mark & x->mark.m) == x->mark.v && ··· 1703 1703 struct xfrm_state *x; 1704 1704 unsigned int i; 1705 1705 1706 - rcu_read_lock(); 1707 1706 for (i = 0; i <= net->xfrm.state_hmask; i++) { 1708 - hlist_for_each_entry_rcu(x, &net->xfrm.state_byspi[i], byspi) { 1709 - if (x->id.spi == spi && x->id.proto == proto) { 1710 - if (!xfrm_state_hold_rcu(x)) 1711 - continue; 1712 - rcu_read_unlock(); 1707 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_byspi, net) + i, byspi) { 1708 + if (x->id.spi == spi && x->id.proto == proto) 1713 1709 return x; 1714 - } 1715 1710 } 1716 1711 } 1717 - rcu_read_unlock(); 1718 1712 return NULL; 1719 1713 } 1720 1714 ··· 1724 1730 1725 1731 h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr, 1726 1732 x->props.reqid, x->props.family); 1727 - XFRM_STATE_INSERT(bydst, &x->bydst, net->xfrm.state_bydst + h, 1733 + XFRM_STATE_INSERT(bydst, &x->bydst, 1734 + xfrm_state_deref_prot(net->xfrm.state_bydst, net) + h, 1728 1735 x->xso.type); 1729 1736 1730 1737 h = xfrm_src_hash(net, &x->id.daddr, &x->props.saddr, x->props.family); 1731 - XFRM_STATE_INSERT(bysrc, &x->bysrc, net->xfrm.state_bysrc + h, 1738 + XFRM_STATE_INSERT(bysrc, &x->bysrc, 1739 + xfrm_state_deref_prot(net->xfrm.state_bysrc, net) + h, 1732 1740 x->xso.type); 1733 1741 1734 1742 if (x->id.spi) { 1735 1743 h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, 1736 1744 x->props.family); 1737 1745 1738 - XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, 1746 + XFRM_STATE_INSERT(byspi, &x->byspi, 1747 + xfrm_state_deref_prot(net->xfrm.state_byspi, net) + h, 1739 1748 x->xso.type); 1740 1749 } 1741 1750 1742 1751 if (x->km.seq) { 1743 1752 h = xfrm_seq_hash(net, x->km.seq); 1744 1753 1745 - XFRM_STATE_INSERT(byseq, &x->byseq, net->xfrm.state_byseq + h, 1754 + XFRM_STATE_INSERT(byseq, &x->byseq, 1755 + xfrm_state_deref_prot(net->xfrm.state_byseq, net) + h, 1746 1756 x->xso.type); 1747 1757 } 1748 1758 ··· 1773 1775 u32 cpu_id = xnew->pcpu_num; 1774 1776 1775 1777 h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family); 1776 - hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) { 1778 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bydst, net) + h, bydst) { 1777 1779 if (x->props.family == family && 1778 1780 x->props.reqid == reqid && 1779 1781 x->if_id == if_id && ··· 1809 1811 struct xfrm_state *x; 1810 1812 u32 mark = m->v & m->m; 1811 1813 1812 - hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) { 1814 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bydst, net) + h, bydst) { 1813 1815 if (x->props.reqid != reqid || 1814 1816 x->props.mode != mode || 1815 1817 x->props.family != family || ··· 1866 1868 ktime_set(net->xfrm.sysctl_acq_expires, 0), 1867 1869 HRTIMER_MODE_REL_SOFT); 1868 1870 list_add(&x->km.all, &net->xfrm.state_all); 1869 - XFRM_STATE_INSERT(bydst, &x->bydst, net->xfrm.state_bydst + h, 1871 + XFRM_STATE_INSERT(bydst, &x->bydst, 1872 + xfrm_state_deref_prot(net->xfrm.state_bydst, net) + h, 1870 1873 x->xso.type); 1871 1874 h = xfrm_src_hash(net, daddr, saddr, family); 1872 - XFRM_STATE_INSERT(bysrc, &x->bysrc, net->xfrm.state_bysrc + h, 1875 + XFRM_STATE_INSERT(bysrc, &x->bysrc, 1876 + xfrm_state_deref_prot(net->xfrm.state_bysrc, net) + h, 1873 1877 x->xso.type); 1874 1878 1875 1879 net->xfrm.state_num++; ··· 2091 2091 if (m->reqid) { 2092 2092 h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr, 2093 2093 m->reqid, m->old_family); 2094 - hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) { 2094 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bydst, net) + h, bydst) { 2095 2095 if (x->props.mode != m->mode || 2096 2096 x->id.proto != m->proto) 2097 2097 continue; ··· 2110 2110 } else { 2111 2111 h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr, 2112 2112 m->old_family); 2113 - hlist_for_each_entry(x, net->xfrm.state_bysrc+h, bysrc) { 2113 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bysrc, net) + h, bysrc) { 2114 2114 if (x->props.mode != m->mode || 2115 2115 x->id.proto != m->proto) 2116 2116 continue; ··· 2264 2264 2265 2265 err = 0; 2266 2266 x->km.state = XFRM_STATE_DEAD; 2267 + xfrm_dev_state_delete(x); 2267 2268 __xfrm_state_put(x); 2268 2269 } 2269 2270 ··· 2313 2312 2314 2313 spin_lock_bh(&net->xfrm.xfrm_state_lock); 2315 2314 for (i = 0; i <= net->xfrm.state_hmask; i++) { 2316 - hlist_for_each_entry(x, net->xfrm.state_bydst + i, bydst) 2315 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_bydst, net) + i, bydst) 2317 2316 xfrm_dev_state_update_stats(x); 2318 2317 } 2319 2318 spin_unlock_bh(&net->xfrm.xfrm_state_lock); ··· 2504 2503 unsigned int h = xfrm_seq_hash(net, seq); 2505 2504 struct xfrm_state *x; 2506 2505 2507 - hlist_for_each_entry_rcu(x, net->xfrm.state_byseq + h, byseq) { 2506 + hlist_for_each_entry(x, xfrm_state_deref_prot(net->xfrm.state_byseq, net) + h, byseq) { 2508 2507 if (x->km.seq == seq && 2509 2508 (mark & x->mark.m) == x->mark.v && 2510 2509 x->pcpu_num == pcpu_num && ··· 2603 2602 if (!x0) { 2604 2603 x->id.spi = newspi; 2605 2604 h = xfrm_spi_hash(net, &x->id.daddr, newspi, x->id.proto, x->props.family); 2606 - XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, x->xso.type); 2605 + XFRM_STATE_INSERT(byspi, &x->byspi, 2606 + xfrm_state_deref_prot(net->xfrm.state_byspi, net) + h, 2607 + x->xso.type); 2607 2608 spin_unlock_bh(&net->xfrm.xfrm_state_lock); 2608 2609 err = 0; 2609 2610 goto unlock; 2610 2611 } 2611 - xfrm_state_put(x0); 2612 2612 spin_unlock_bh(&net->xfrm.xfrm_state_lock); 2613 2613 2614 2614 next: ··· 3260 3258 3261 3259 int __net_init xfrm_state_init(struct net *net) 3262 3260 { 3261 + struct hlist_head *ndst, *nsrc, *nspi, *nseq; 3263 3262 unsigned int sz; 3264 3263 3265 3264 if (net_eq(net, &init_net)) ··· 3271 3268 3272 3269 sz = sizeof(struct hlist_head) * 8; 3273 3270 3274 - net->xfrm.state_bydst = xfrm_hash_alloc(sz); 3275 - if (!net->xfrm.state_bydst) 3271 + ndst = xfrm_hash_alloc(sz); 3272 + if (!ndst) 3276 3273 goto out_bydst; 3277 - net->xfrm.state_bysrc = xfrm_hash_alloc(sz); 3278 - if (!net->xfrm.state_bysrc) 3274 + rcu_assign_pointer(net->xfrm.state_bydst, ndst); 3275 + 3276 + nsrc = xfrm_hash_alloc(sz); 3277 + if (!nsrc) 3279 3278 goto out_bysrc; 3280 - net->xfrm.state_byspi = xfrm_hash_alloc(sz); 3281 - if (!net->xfrm.state_byspi) 3279 + rcu_assign_pointer(net->xfrm.state_bysrc, nsrc); 3280 + 3281 + nspi = xfrm_hash_alloc(sz); 3282 + if (!nspi) 3282 3283 goto out_byspi; 3283 - net->xfrm.state_byseq = xfrm_hash_alloc(sz); 3284 - if (!net->xfrm.state_byseq) 3284 + rcu_assign_pointer(net->xfrm.state_byspi, nspi); 3285 + 3286 + nseq = xfrm_hash_alloc(sz); 3287 + if (!nseq) 3285 3288 goto out_byseq; 3289 + rcu_assign_pointer(net->xfrm.state_byseq, nseq); 3286 3290 3287 3291 net->xfrm.state_cache_input = alloc_percpu(struct hlist_head); 3288 3292 if (!net->xfrm.state_cache_input) ··· 3305 3295 return 0; 3306 3296 3307 3297 out_state_cache_input: 3308 - xfrm_hash_free(net->xfrm.state_byseq, sz); 3298 + xfrm_hash_free(nseq, sz); 3309 3299 out_byseq: 3310 - xfrm_hash_free(net->xfrm.state_byspi, sz); 3300 + xfrm_hash_free(nspi, sz); 3311 3301 out_byspi: 3312 - xfrm_hash_free(net->xfrm.state_bysrc, sz); 3302 + xfrm_hash_free(nsrc, sz); 3313 3303 out_bysrc: 3314 - xfrm_hash_free(net->xfrm.state_bydst, sz); 3304 + xfrm_hash_free(ndst, sz); 3315 3305 out_bydst: 3316 3306 return -ENOMEM; 3317 3307 } 3318 3308 3309 + #define xfrm_state_deref_netexit(table) \ 3310 + rcu_dereference_protected((table), true /* netns is going away */) 3319 3311 void xfrm_state_fini(struct net *net) 3320 3312 { 3321 3313 unsigned int sz; ··· 3330 3318 WARN_ON(!list_empty(&net->xfrm.state_all)); 3331 3319 3332 3320 for (i = 0; i <= net->xfrm.state_hmask; i++) { 3333 - WARN_ON(!hlist_empty(net->xfrm.state_byseq + i)); 3334 - WARN_ON(!hlist_empty(net->xfrm.state_byspi + i)); 3335 - WARN_ON(!hlist_empty(net->xfrm.state_bysrc + i)); 3336 - WARN_ON(!hlist_empty(net->xfrm.state_bydst + i)); 3321 + WARN_ON(!hlist_empty(xfrm_state_deref_netexit(net->xfrm.state_byseq) + i)); 3322 + WARN_ON(!hlist_empty(xfrm_state_deref_netexit(net->xfrm.state_byspi) + i)); 3323 + WARN_ON(!hlist_empty(xfrm_state_deref_netexit(net->xfrm.state_bysrc) + i)); 3324 + WARN_ON(!hlist_empty(xfrm_state_deref_netexit(net->xfrm.state_bydst) + i)); 3337 3325 } 3338 3326 3339 3327 sz = (net->xfrm.state_hmask + 1) * sizeof(struct hlist_head); 3340 - xfrm_hash_free(net->xfrm.state_byseq, sz); 3341 - xfrm_hash_free(net->xfrm.state_byspi, sz); 3342 - xfrm_hash_free(net->xfrm.state_bysrc, sz); 3343 - xfrm_hash_free(net->xfrm.state_bydst, sz); 3328 + xfrm_hash_free(xfrm_state_deref_netexit(net->xfrm.state_byseq), sz); 3329 + xfrm_hash_free(xfrm_state_deref_netexit(net->xfrm.state_byspi), sz); 3330 + xfrm_hash_free(xfrm_state_deref_netexit(net->xfrm.state_bysrc), sz); 3331 + xfrm_hash_free(xfrm_state_deref_netexit(net->xfrm.state_bydst), sz); 3344 3332 free_percpu(net->xfrm.state_cache_input); 3345 3333 } 3346 3334
+22 -10
net/xfrm/xfrm_user.c
··· 35 35 #endif 36 36 #include <linux/unaligned.h> 37 37 38 + static struct sock *xfrm_net_nlsk(const struct net *net, const struct sk_buff *skb) 39 + { 40 + /* get the source of this request, see netlink_unicast_kernel */ 41 + const struct sock *sk = NETLINK_CB(skb).sk; 42 + 43 + /* sk is refcounted, the netns stays alive and nlsk with it */ 44 + return rcu_dereference_protected(net->xfrm.nlsk, sk->sk_net_refcnt); 45 + } 46 + 38 47 static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type, 39 48 struct netlink_ext_ack *extack) 40 49 { ··· 1736 1727 err = build_spdinfo(r_skb, net, sportid, seq, *flags); 1737 1728 BUG_ON(err < 0); 1738 1729 1739 - return nlmsg_unicast(net->xfrm.nlsk, r_skb, sportid); 1730 + return nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, sportid); 1740 1731 } 1741 1732 1742 1733 static inline unsigned int xfrm_sadinfo_msgsize(void) ··· 1796 1787 err = build_sadinfo(r_skb, net, sportid, seq, *flags); 1797 1788 BUG_ON(err < 0); 1798 1789 1799 - return nlmsg_unicast(net->xfrm.nlsk, r_skb, sportid); 1790 + return nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, sportid); 1800 1791 } 1801 1792 1802 1793 static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, ··· 1816 1807 if (IS_ERR(resp_skb)) { 1817 1808 err = PTR_ERR(resp_skb); 1818 1809 } else { 1819 - err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid); 1810 + err = nlmsg_unicast(xfrm_net_nlsk(net, skb), resp_skb, NETLINK_CB(skb).portid); 1820 1811 } 1821 1812 xfrm_state_put(x); 1822 1813 out_noput: ··· 1859 1850 pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]); 1860 1851 if (pcpu_num >= num_possible_cpus()) { 1861 1852 err = -EINVAL; 1853 + NL_SET_ERR_MSG(extack, "pCPU number too big"); 1862 1854 goto out_noput; 1863 1855 } 1864 1856 } ··· 1907 1897 } 1908 1898 } 1909 1899 1910 - err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid); 1900 + err = nlmsg_unicast(xfrm_net_nlsk(net, skb), resp_skb, NETLINK_CB(skb).portid); 1911 1901 1912 1902 out: 1913 1903 xfrm_state_put(x); ··· 2552 2542 r_up->out = net->xfrm.policy_default[XFRM_POLICY_OUT]; 2553 2543 nlmsg_end(r_skb, r_nlh); 2554 2544 2555 - return nlmsg_unicast(net->xfrm.nlsk, r_skb, portid); 2545 + return nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, portid); 2556 2546 } 2557 2547 2558 2548 static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, ··· 2618 2608 if (IS_ERR(resp_skb)) { 2619 2609 err = PTR_ERR(resp_skb); 2620 2610 } else { 2621 - err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, 2611 + err = nlmsg_unicast(xfrm_net_nlsk(net, skb), resp_skb, 2622 2612 NETLINK_CB(skb).portid); 2623 2613 } 2624 2614 } else { ··· 2791 2781 err = build_aevent(r_skb, x, &c); 2792 2782 BUG_ON(err < 0); 2793 2783 2794 - err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).portid); 2784 + err = nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, NETLINK_CB(skb).portid); 2795 2785 spin_unlock_bh(&x->lock); 2796 2786 xfrm_state_put(x); 2797 2787 return err; ··· 3011 3001 if (attrs[XFRMA_SA_PCPU]) { 3012 3002 x->pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]); 3013 3003 err = -EINVAL; 3014 - if (x->pcpu_num >= num_possible_cpus()) 3004 + if (x->pcpu_num >= num_possible_cpus()) { 3005 + NL_SET_ERR_MSG(extack, "pCPU number too big"); 3015 3006 goto free_state; 3007 + } 3016 3008 } 3017 3009 3018 3010 err = verify_newpolicy_info(&ua->policy, extack); ··· 3495 3483 goto err; 3496 3484 } 3497 3485 3498 - err = netlink_dump_start(net->xfrm.nlsk, skb, nlh, &c); 3486 + err = netlink_dump_start(xfrm_net_nlsk(net, skb), skb, nlh, &c); 3499 3487 goto err; 3500 3488 } 3501 3489 ··· 3685 3673 } 3686 3674 if (x->if_id) 3687 3675 l += nla_total_size(sizeof(x->if_id)); 3688 - if (x->pcpu_num) 3676 + if (x->pcpu_num != UINT_MAX) 3689 3677 l += nla_total_size(sizeof(x->pcpu_num)); 3690 3678 3691 3679 /* Must count x->lastused as it may become non-zero behind our back. */