Linux kernel -stable discussions
 help / color / mirror / Atom feed
* [PATCH net 1/2] ipmr: fully initialize the synthetic IP header in ipmr_get_route()
       [not found] <20261025071729.34967-1-idosch@nvidia.com>
@ 2026-10-25  7:17 ` Ido Schimmel
  2026-10-25 10:50   ` Eric Dumazet
  2026-10-25  7:17 ` [PATCH net 2/2] ipmr, ip6mr: validate packets injected into the register vif on xmit Ido Schimmel
  1 sibling, 1 reply; 5+ messages in thread
From: Ido Schimmel @ 2026-10-25  7:17 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, pabeni, edumazet, dsahern, horms, yoshfuji,
	Ido Schimmel, stable

For an unresolved multicast route query, ipmr_get_route() builds a
synthetic IP header in the headroom obtained from
skb_realloc_headroom(), which does not zero the memory it allocates.
Only a few fields are initialized, leaving others as stale heap
contents.

ipmr_cache_report() copies this header into the IGMPMSG_NOCACHE report
that is queued to the mroute socket, so a recvmsg() on that socket leaks
the uninitialized bytes to user space: the 'tos' field [1] and the 'id'
and 'frag_off' fields [2].

Fix by zeroing the IP header before filling in the few fields that are
used, so that the entire header is initialized, as in ip6mr_get_route().

[1]
BUG: KMSAN: kernel-infoleak in _copy_to_iter
 raw_recvmsg

Uninit was stored to memory at:
 ipmr_cache_report
 ipmr_cache_unresolved
 ipmr_get_route

Uninit was created at:
 pskb_expand_head
 skb_realloc_headroom
 ipmr_get_route

Byte 1 of 28 is uninitialized

[2]
BUG: KMSAN: kernel-infoleak in _copy_to_iter
 raw_recvmsg

Uninit was stored to memory at:
 ipmr_cache_report
 ipmr_cache_unresolved
 ipmr_get_route

Uninit was created at:
 pskb_expand_head
 skb_realloc_headroom
 ipmr_get_route

Bytes 4-7 of 28 are uninitialized

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <netdev-bot+sashiko@kernel.org>
Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/0545f0c83f5ee2f6696210f87268e811ef655715.1792476357.git.zhilinz%40nebusec.ai
Assisted-by: LLM
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 net/ipv4/ipmr.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index acacaae05cc4..eac23f251bfd 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -2506,6 +2506,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;
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net 2/2] ipmr, ip6mr: validate packets injected into the register vif on xmit
       [not found] <20261025071729.34967-1-idosch@nvidia.com>
  2026-10-25  7:17 ` [PATCH net 1/2] ipmr: fully initialize the synthetic IP header in ipmr_get_route() Ido Schimmel
@ 2026-10-25  7:17 ` Ido Schimmel
  2026-10-25 10:52   ` Eric Dumazet
  2026-10-26 23:39   ` Jakub Kicinski
  1 sibling, 2 replies; 5+ messages in thread
From: Ido Schimmel @ 2026-10-25  7:17 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, pabeni, edumazet, dsahern, horms, yoshfuji,
	Ido Schimmel, stable

reg_vif_xmit() passes the packet to ipmr_cache_report() which copies its
IP header into the IGMPMSG_WHOLEPKT report that is queued to the mroute
socket. Nothing guarantees that the packet contains a full IP header, so
when a short packet is injected on the register device (e.g., using
AF_PACKET), the copy reads past the end of the packet and a recvmsg() on
the mroute socket leaks the uninitialized bytes to user space [1].

IPv6 has the same problem [2]. Its reg_vif_xmit() does call
pskb_inet_may_pull(), but the helper keys off skb->protocol and does not
pull anything when the protocol is neither IPv4 nor IPv6.

Fix by dropping packets whose protocol does not match the address family
of the register device or that do not contain a full network header.

[1]
BUG: KMSAN: kernel-infoleak in _copy_to_iter
 raw_recvmsg

Uninit was stored to memory at:
 ipmr_cache_report
 reg_vif_xmit
 packet_sendmsg

Uninit was created at:
 __alloc_skb
 sock_alloc_send_pskb
 packet_sendmsg

Bytes 1-3 of 21 are uninitialized

[2]
BUG: KMSAN: kernel-infoleak in _copy_to_iter
 rawv6_recvmsg

Uninit was stored to memory at:
 ip6mr_cache_report
 reg_vif_xmit
 packet_sendmsg

Uninit was created at:
 __alloc_skb
 sock_alloc_send_pskb
 packet_sendmsg

Bytes 8-23 of 41 are uninitialized

Fixes: 14fb64e1f449 ("[IPV6] MROUTE: Support PIM-SM (SSM).")
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <netdev-bot+sashiko@kernel.org>
Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/0545f0c83f5ee2f6696210f87268e811ef655715.1792476357.git.zhilinz%40nebusec.ai
Assisted-by: LLM
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 net/ipv4/ipmr.c  | 6 ++++++
 net/ipv6/ip6mr.c | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index eac23f251bfd..d6691c917af4 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -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) {
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 3a551be30f15..a628acf50b0d 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -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();
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net 1/2] ipmr: fully initialize the synthetic IP header in ipmr_get_route()
  2026-10-25  7:17 ` [PATCH net 1/2] ipmr: fully initialize the synthetic IP header in ipmr_get_route() Ido Schimmel
@ 2026-10-25 10:50   ` Eric Dumazet
  0 siblings, 0 replies; 5+ messages in thread
From: Eric Dumazet @ 2026-10-25 10:50 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, kuba, pabeni, dsahern, horms, yoshfuji, stable

Le dim. 25 oct. 2026 à 08:18, Ido Schimmel <idosch@nvidia.com> a écrit :
>
> For an unresolved multicast route query, ipmr_get_route() builds a
> synthetic IP header in the headroom obtained from
> skb_realloc_headroom(), which does not zero the memory it allocates.
> Only a few fields are initialized, leaving others as stale heap
> contents.
>
> ipmr_cache_report() copies this header into the IGMPMSG_NOCACHE report
> that is queued to the mroute socket, so a recvmsg() on that socket leaks
> the uninitialized bytes to user space: the 'tos' field [1] and the 'id'
> and 'frag_off' fields [2].
>
> Fix by zeroing the IP header before filling in the few fields that are
> used, so that the entire header is initialized, as in ip6mr_get_route().
>
> [1]
> BUG: KMSAN: kernel-infoleak in _copy_to_iter
>  raw_recvmsg
>
> Uninit was stored to memory at:
>  ipmr_cache_report
>  ipmr_cache_unresolved
>  ipmr_get_route
>
> Uninit was created at:
>  pskb_expand_head
>  skb_realloc_headroom
>  ipmr_get_route
>
> Byte 1 of 28 is uninitialized
>
> [2]
> BUG: KMSAN: kernel-infoleak in _copy_to_iter
>  raw_recvmsg
>
> Uninit was stored to memory at:
>  ipmr_cache_report
>  ipmr_cache_unresolved
>  ipmr_get_route
>
> Uninit was created at:
>  pskb_expand_head
>  skb_realloc_headroom
>  ipmr_get_route
>
> Bytes 4-7 of 28 are uninitialized
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: stable@vger.kernel.org
> Reported-by: Sashiko <netdev-bot+sashiko@kernel.org>
> Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/0545f0c83f5ee2f6696210f87268e811ef655715.1792476357.git.zhilinz%40nebusec.ai
> Assisted-by: LLM
> Signed-off-by: Ido Schimmel <idosch@nvidia.com>
> ---
>  net/ipv4/ipmr.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
> index acacaae05cc4..eac23f251bfd 100644
> --- a/net/ipv4/ipmr.c
> +++ b/net/ipv4/ipmr.c
> @@ -2506,6 +2506,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;

Reviewed-by: Eric Dumazet <edumazet@kernel.org>

SGTM, I will send this follow up as a separate patch.

diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index acacaae05cc49dc15910f23f7539865432518587..8b84142fd7754d95aa1f2facf68ac554916efd27
100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -550,6 +550,11 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff
*skb, struct net_device *dev)
        DEV_STATS_ADD(dev, tx_bytes, skb->len);
        DEV_STATS_INC(dev, tx_packets);

+       /* skb->cb[] holds qdisc/tc state at this point, not IPCB.
+        * ipmr_cache_report() reads it as IPCB to build IP_PKTINFO.
+        */
+       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+
        /* Pairs with WRITE_ONCE() in vif_add() and vif_delete() */
        ipmr_cache_report(mrt, skb, READ_ONCE(mrt->mroute_reg_vif_num),
                          IGMPMSG_WHOLEPKT);

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net 2/2] ipmr, ip6mr: validate packets injected into the register vif on xmit
  2026-10-25  7:17 ` [PATCH net 2/2] ipmr, ip6mr: validate packets injected into the register vif on xmit Ido Schimmel
@ 2026-10-25 10:52   ` Eric Dumazet
  2026-10-26 23:39   ` Jakub Kicinski
  1 sibling, 0 replies; 5+ messages in thread
From: Eric Dumazet @ 2026-10-25 10:52 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, kuba, pabeni, dsahern, horms, yoshfuji, stable

Le dim. 25 oct. 2026 à 08:18, Ido Schimmel <idosch@nvidia.com> a écrit :
>
> reg_vif_xmit() passes the packet to ipmr_cache_report() which copies its
> IP header into the IGMPMSG_WHOLEPKT report that is queued to the mroute
> socket. Nothing guarantees that the packet contains a full IP header, so
> when a short packet is injected on the register device (e.g., using
> AF_PACKET), the copy reads past the end of the packet and a recvmsg() on
> the mroute socket leaks the uninitialized bytes to user space [1].
>
> IPv6 has the same problem [2]. Its reg_vif_xmit() does call
> pskb_inet_may_pull(), but the helper keys off skb->protocol and does not
> pull anything when the protocol is neither IPv4 nor IPv6.
>
> Fix by dropping packets whose protocol does not match the address family
> of the register device or that do not contain a full network header.
>

Reviewed-by: Eric Dumazet <edumazet@kernel.org>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net 2/2] ipmr, ip6mr: validate packets injected into the register vif on xmit
  2026-10-25  7:17 ` [PATCH net 2/2] ipmr, ip6mr: validate packets injected into the register vif on xmit Ido Schimmel
  2026-10-25 10:52   ` Eric Dumazet
@ 2026-10-26 23:39   ` Jakub Kicinski
  1 sibling, 0 replies; 5+ messages in thread
From: Jakub Kicinski @ 2026-10-26 23:39 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, pabeni, edumazet, dsahern, horms, yoshfuji, stable

On Sun, 25 Oct 2026 09:17:29 +0200 Ido Schimmel wrote:
> Assisted-by: LLM

Hi Ido! FWIW these are no longer necessary.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-10-26 23:39 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20261025071729.34967-1-idosch@nvidia.com>
2026-10-25  7:17 ` [PATCH net 1/2] ipmr: fully initialize the synthetic IP header in ipmr_get_route() Ido Schimmel
2026-10-25 10:50   ` Eric Dumazet
2026-10-25  7:17 ` [PATCH net 2/2] ipmr, ip6mr: validate packets injected into the register vif on xmit Ido Schimmel
2026-10-25 10:52   ` Eric Dumazet
2026-10-26 23:39   ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox