ipsec-2026-04-08

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEH7ZpcWbFyOOp6OJbrB3Eaf9PW7cFAmnWJAkACgkQrB3Eaf9P
 W7cPzxAAgYsuMeJBQLG5zwBS345iX/sRSJKLpw9Qosgy9f6GC7WFc55bcsl63BiS
 wWKMGUGKfkOGO1OMdZ+I2XkGYKvdPGARRq5vSenKZEf+5D+KzQSY5+s/lDzw8V9c
 LWRyhKB2OmFHOmAAGfoGKu/9b4CHRCOMXtigY4gVGO50v89VkQP/zE9zL5Y4GU/z
 5YBUGkrTOA+nVV2NdNauBmb/CuZIL8iMs3+zlNT9QjY+4qzmLFKqcZ85xL7rOIqG
 4KviHOKhU1wixTvMYEpyLluqmU7SpKaLrmlbGXz4bLDJLzEsn4wTe0FSrQ6mXZWV
 fkGyDpzKeIN4us8k98PW8oJPeyaiBEQVNouAr3sFf1dE8nOZK10s7pKDuf3VNPQC
 Qt+bF56Ob/koHOPtcfV8RmsKqjLkrKd2Tnm0oxBukFjA1UFEwnB4oHRDvBzz6cYW
 Hv6/+bYo9+LIPRnaz8Zufxfel3mpq29wjFc0YTt9TtXKcyyhPRaAkMn3f1LPJ3EU
 eKzM33qc1VOD7PgyAQem4uC//IHvgat2xlZn+zZ2AKVphIsglsHdjVGY9LZpGEh2
 MC8G4AxYryigtMsnG9EOFsluaDFoNZ3qqxukS1AvxXFGGY/MQ83vZSf8SMovd2YH
 V7PupKGGNvt50ZaAjbgPxZg3ZvHy5+3T5fqG4cjKBuG1JH+Vngw=
 =vtxh
 -----END PGP SIGNATURE-----

Merge tag 'ipsec-2026-04-08' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2026-04-08

1) Clear trailing padding in build_polexpire() to prevent
   leaking unititialized memory. From Yasuaki Torimaru.

2) Fix aevent size calculation when XFRMA_IF_ID is used.
   From Keenan Dong.

3) Wait for RCU readers during policy netns exit before
   freeing the policy hash tables.

4) Fix dome too eaerly dropped references on the netdev
   when uding transport mode. From Qi Tang.

5) Fix refcount leak in xfrm_migrate_policy_find().
   From Kotlyarov Mihail.

6) Fix two fix info leaks in build_report() and
   in build_mapping(). From Greg Kroah-Hartman.

7) Zero aligned sockaddr tail in PF_KEY exports.
   From Zhengchuan Liang.

* tag 'ipsec-2026-04-08' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec:
  net: af_key: zero aligned sockaddr tail in PF_KEY exports
  xfrm_user: fix info leak in build_report()
  xfrm_user: fix info leak in build_mapping()
  xfrm: fix refcount leak in xfrm_migrate_policy_find
  xfrm: hold dev ref until after transport_finish NF_HOOK
  xfrm: Wait for RCU readers during policy netns exit
  xfrm: account XFRMA_IF_ID in aevent size calculation
  xfrm: clear trailing padding in build_polexpire()
====================

Link: https://patch.msgid.link/20260408095925.253681-1-steffen.klassert@secunet.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
master
Jakub Kicinski 2026-04-08 18:54:31 -07:00
commit 84ac9a922d
6 changed files with 70 additions and 29 deletions

View File

@ -50,6 +50,7 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async)
{
struct xfrm_offload *xo = xfrm_offload(skb);
struct iphdr *iph = ip_hdr(skb);
struct net_device *dev = skb->dev;
iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
@ -73,8 +74,10 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async)
}
NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,
dev_net(skb->dev), NULL, skb, skb->dev, NULL,
dev_net(dev), NULL, skb, dev, NULL,
xfrm4_rcv_encap_finish);
if (async)
dev_put(dev);
return 0;
}

View File

@ -43,6 +43,7 @@ static int xfrm6_transport_finish2(struct net *net, struct sock *sk,
int xfrm6_transport_finish(struct sk_buff *skb, int async)
{
struct xfrm_offload *xo = xfrm_offload(skb);
struct net_device *dev = skb->dev;
int nhlen = -skb_network_offset(skb);
skb_network_header(skb)[IP6CB(skb)->nhoff] =
@ -68,8 +69,10 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
}
NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
dev_net(skb->dev), NULL, skb, skb->dev, NULL,
dev_net(dev), NULL, skb, dev, NULL,
xfrm6_transport_finish2);
if (async)
dev_put(dev);
return 0;
}

View File

@ -757,6 +757,22 @@ static unsigned int pfkey_sockaddr_fill(const xfrm_address_t *xaddr, __be16 port
return 0;
}
static unsigned int pfkey_sockaddr_fill_zero_tail(const xfrm_address_t *xaddr,
__be16 port,
struct sockaddr *sa,
unsigned short family)
{
unsigned int prefixlen;
int sockaddr_len = pfkey_sockaddr_len(family);
int sockaddr_size = pfkey_sockaddr_size(family);
prefixlen = pfkey_sockaddr_fill(xaddr, port, sa, family);
if (sockaddr_size > sockaddr_len)
memset((u8 *)sa + sockaddr_len, 0, sockaddr_size - sockaddr_len);
return prefixlen;
}
static struct sk_buff *__pfkey_xfrm_state2msg(const struct xfrm_state *x,
int add_keys, int hsc)
{
@ -3206,9 +3222,9 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
addr->sadb_address_proto = 0;
addr->sadb_address_reserved = 0;
addr->sadb_address_prefixlen =
pfkey_sockaddr_fill(&x->props.saddr, 0,
(struct sockaddr *) (addr + 1),
x->props.family);
pfkey_sockaddr_fill_zero_tail(&x->props.saddr, 0,
(struct sockaddr *)(addr + 1),
x->props.family);
if (!addr->sadb_address_prefixlen)
BUG();
@ -3221,9 +3237,9 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
addr->sadb_address_proto = 0;
addr->sadb_address_reserved = 0;
addr->sadb_address_prefixlen =
pfkey_sockaddr_fill(&x->id.daddr, 0,
(struct sockaddr *) (addr + 1),
x->props.family);
pfkey_sockaddr_fill_zero_tail(&x->id.daddr, 0,
(struct sockaddr *)(addr + 1),
x->props.family);
if (!addr->sadb_address_prefixlen)
BUG();
@ -3421,9 +3437,9 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
addr->sadb_address_proto = 0;
addr->sadb_address_reserved = 0;
addr->sadb_address_prefixlen =
pfkey_sockaddr_fill(&x->props.saddr, 0,
(struct sockaddr *) (addr + 1),
x->props.family);
pfkey_sockaddr_fill_zero_tail(&x->props.saddr, 0,
(struct sockaddr *)(addr + 1),
x->props.family);
if (!addr->sadb_address_prefixlen)
BUG();
@ -3443,9 +3459,9 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
addr->sadb_address_proto = 0;
addr->sadb_address_reserved = 0;
addr->sadb_address_prefixlen =
pfkey_sockaddr_fill(ipaddr, 0,
(struct sockaddr *) (addr + 1),
x->props.family);
pfkey_sockaddr_fill_zero_tail(ipaddr, 0,
(struct sockaddr *)(addr + 1),
x->props.family);
if (!addr->sadb_address_prefixlen)
BUG();
@ -3474,15 +3490,15 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type,
switch (type) {
case SADB_EXT_ADDRESS_SRC:
addr->sadb_address_prefixlen = sel->prefixlen_s;
pfkey_sockaddr_fill(&sel->saddr, 0,
(struct sockaddr *)(addr + 1),
sel->family);
pfkey_sockaddr_fill_zero_tail(&sel->saddr, 0,
(struct sockaddr *)(addr + 1),
sel->family);
break;
case SADB_EXT_ADDRESS_DST:
addr->sadb_address_prefixlen = sel->prefixlen_d;
pfkey_sockaddr_fill(&sel->daddr, 0,
(struct sockaddr *)(addr + 1),
sel->family);
pfkey_sockaddr_fill_zero_tail(&sel->daddr, 0,
(struct sockaddr *)(addr + 1),
sel->family);
break;
default:
return -EINVAL;

View File

@ -506,7 +506,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
/* An encap_type of -1 indicates async resumption. */
if (encap_type == -1) {
async = 1;
dev_put(skb->dev);
seq = XFRM_SKB_CB(skb)->seq.input.low;
spin_lock(&x->lock);
goto resume;
@ -659,8 +658,11 @@ process:
dev_hold(skb->dev);
nexthdr = x->type->input(x, skb);
if (nexthdr == -EINPROGRESS)
if (nexthdr == -EINPROGRESS) {
if (async)
dev_put(skb->dev);
return 0;
}
dev_put(skb->dev);
spin_lock(&x->lock);
@ -695,9 +697,11 @@ resume:
XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
err = xfrm_inner_mode_input(x, skb);
if (err == -EINPROGRESS)
if (err == -EINPROGRESS) {
if (async)
dev_put(skb->dev);
return 0;
else if (err) {
} else if (err) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
goto drop;
}
@ -734,6 +738,8 @@ resume_decapped:
sp->olen = 0;
if (skb_valid_dst(skb))
skb_dst_drop(skb);
if (async)
dev_put(skb->dev);
gro_cells_receive(&gro_cells, skb);
return 0;
} else {
@ -753,6 +759,8 @@ resume_decapped:
sp->olen = 0;
if (skb_valid_dst(skb))
skb_dst_drop(skb);
if (async)
dev_put(skb->dev);
gro_cells_receive(&gro_cells, skb);
return err;
}
@ -763,6 +771,8 @@ resume_decapped:
drop_unlock:
spin_unlock(&x->lock);
drop:
if (async)
dev_put(skb->dev);
xfrm_rcv_cb(skb, family, x && x->type ? x->type->proto : nexthdr, -1);
kfree_skb(skb);
return 0;

View File

@ -4290,6 +4290,8 @@ static void xfrm_policy_fini(struct net *net)
#endif
xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, false);
synchronize_rcu();
WARN_ON(!list_empty(&net->xfrm.policy_all));
for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
@ -4526,9 +4528,6 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *
pol = xfrm_policy_lookup_bytype(net, type, &fl, sel->family, dir, if_id);
if (IS_ERR_OR_NULL(pol))
goto out_unlock;
if (!xfrm_pol_hold_rcu(pol))
pol = NULL;
out_unlock:
rcu_read_unlock();
return pol;

View File

@ -2677,7 +2677,8 @@ static inline unsigned int xfrm_aevent_msgsize(struct xfrm_state *x)
+ nla_total_size(4) /* XFRM_AE_RTHR */
+ nla_total_size(4) /* XFRM_AE_ETHR */
+ nla_total_size(sizeof(x->dir)) /* XFRMA_SA_DIR */
+ nla_total_size(4); /* XFRMA_SA_PCPU */
+ nla_total_size(4) /* XFRMA_SA_PCPU */
+ nla_total_size(sizeof(x->if_id)); /* XFRMA_IF_ID */
}
static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
@ -2789,7 +2790,12 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
c.portid = nlh->nlmsg_pid;
err = build_aevent(r_skb, x, &c);
BUG_ON(err < 0);
if (err < 0) {
spin_unlock_bh(&x->lock);
xfrm_state_put(x);
kfree_skb(r_skb);
return err;
}
err = nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, NETLINK_CB(skb).portid);
spin_unlock_bh(&x->lock);
@ -3960,6 +3966,8 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
return err;
}
upe->hard = !!hard;
/* clear the padding bytes */
memset_after(upe, 0, hard);
nlmsg_end(skb, nlh);
return 0;
@ -4117,6 +4125,7 @@ static int build_report(struct sk_buff *skb, u8 proto,
return -EMSGSIZE;
ur = nlmsg_data(nlh);
memset(ur, 0, sizeof(*ur));
ur->proto = proto;
memcpy(&ur->sel, sel, sizeof(ur->sel));
@ -4164,6 +4173,7 @@ static int build_mapping(struct sk_buff *skb, struct xfrm_state *x,
um = nlmsg_data(nlh);
memset(&um->id, 0, sizeof(um->id));
memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr));
um->id.spi = x->id.spi;
um->id.family = x->props.family;