Merge branch 'ipmr-ip6mr-fix-several-info-leaks'

Ido Schimmel says:

====================
ipmr, ip6mr: Fix several info leaks

ip{,6}mr_cache_report() copy the IP header of a packet that triggered an
upcall to a report packet that is delivered to user space. The header
is not always fully initialized or present, resulting in info leaks
flagged by KMSAN.

Patch 1 fixes an info leak in the RTM_GETROUTE path, caused by the fact
that ipmr_get_route() does not fully initialize the IP header of the
packet that it creates. IPv6 does not suffer from this problem.

Patch 2 fixes info leaks triggered by packets injected into pim{,6}reg
devices via AF_PACKET sockets. The kernel does not validate that these
are IP packets that carry an IP header before calling
ip{,6}mr_cache_report().

Both issues were reported by Sashiko and reproduced by me. See KMSAN
traces in the commit messages.

As far as I can tell, all other callers call these functions from the IP
input / output paths and therefore provide a valid IP packet, with the
exception of ip6mr_get_route() which fully initializes the header of the
packet it creates.
====================

Link: https://patch.msgid.link/20261025071729.34967-1-idosch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-10-26 16:38:33 -07:00
commit a894b4077d
2 changed files with 8 additions and 1 deletions

View File

@ -539,6 +539,12 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
};
int err;
if (skb->protocol != htons(ETH_P_IP) || !pskb_inet_may_pull(skb)) {
DEV_STATS_INC(dev, tx_errors);
kfree_skb(skb);
return NETDEV_TX_OK;
}
rcu_read_lock();
err = ipmr_fib_lookup(net, &fl4, &mrt);
if (err < 0) {
@ -2511,6 +2517,7 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
skb_push(skb2, sizeof(struct iphdr));
skb_reset_network_header(skb2);
iph = ip_hdr(skb2);
memset(iph, 0, sizeof(*iph));
iph->ihl = sizeof(struct iphdr) >> 2;
iph->saddr = saddr;
iph->daddr = daddr;

View File

@ -642,7 +642,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
.flowi6_mark = skb->mark,
};
if (!pskb_inet_may_pull(skb))
if (skb->protocol != htons(ETH_P_IPV6) || !pskb_inet_may_pull(skb))
goto tx_err;
rcu_read_lock();