Skip to content

Commit 916ec74

Browse files
kylebot-oaigregkh
authored andcommitted
batman-adv: reject unrepresentable multicast TVLV offsets
commit f12c2de upstream. The network and transport header fields in struct sk_buff are 16-bit offsets from skb->head, and U16_MAX is reserved as the unset transport header value. batadv_tvlv_call_handler() sets both fields from a received multicast TVLV without checking whether the TVLV end is representable. If the end offset exceeds the field's range, skb_set_transport_header() truncates it so that the transport header precedes the network header. The negative difference is then returned by skb_network_header_len() as a large u32. batadv_mcast_forw_packet() consequently accepts an oversized multicast tracker and accesses memory beyond the skb data. Add skb_set_transport_header_careful(), an offset-aware counterpart to skb_reset_transport_header_careful(), which validates the final head-relative offset before assigning it. Use the new helper in batadv_tvlv_call_handler() and reject unrepresentable TVLVs before setting the network header. Fixes: 07afe1b ("batman-adv: mcast: implement multicast packet reception and forwarding") Cc: stable@vger.kernel.org Signed-off-by: Kyle Zeng <kylebot@openai.com> Co-developed-by: David Lee <david.lee@trailofbits.com> Signed-off-by: David Lee <david.lee@trailofbits.com> Acked-by: Sven Eckelmann <sven@narfation.org> Link: https://patch.msgid.link/20260817084955.944189-1-david.lee@trailofbits.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 3e4476e commit 916ec74

2 files changed

Lines changed: 28 additions & 1 deletion

File tree

include/linux/skbuff.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3110,6 +3110,30 @@ static inline void skb_set_transport_header(struct sk_buff *skb,
31103110
skb->transport_header += offset;
31113111
}
31123112

3113+
/**
3114+
* skb_set_transport_header_careful - conditionally set transport header
3115+
* @skb: buffer to alter
3116+
* @offset: offset to add to skb->data
3117+
*
3118+
* Hardened version of skb_set_transport_header().
3119+
*
3120+
* Returns: true if the operation was a success.
3121+
*/
3122+
static inline bool __must_check
3123+
skb_set_transport_header_careful(struct sk_buff *skb, const int offset)
3124+
{
3125+
long thoff = skb->data - skb->head + offset;
3126+
3127+
if (unlikely(thoff != (typeof(skb->transport_header))thoff))
3128+
return false;
3129+
3130+
if (unlikely(thoff == (typeof(skb->transport_header))~0U))
3131+
return false;
3132+
3133+
skb->transport_header = thoff;
3134+
return true;
3135+
}
3136+
31133137
static inline unsigned char *skb_network_header(const struct sk_buff *skb)
31143138
{
31153139
return skb->head + skb->network_header;

net/batman-adv/tvlv.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,11 @@ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
420420
return NET_RX_SUCCESS;
421421

422422
tvlv_offset = (unsigned char *)tvlv_value - skb->data;
423+
if (!skb_set_transport_header_careful(skb,
424+
tvlv_offset + tvlv_value_len))
425+
return -EINVAL;
426+
423427
skb_set_network_header(skb, tvlv_offset);
424-
skb_set_transport_header(skb, tvlv_offset + tvlv_value_len);
425428

426429
return tvlv_handler->mcast_handler(bat_priv, skb);
427430
}

0 commit comments

Comments
 (0)