summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorKyle Zeng <kylebot@openai.com>2026-08-17 08:49:54 +0000
committerJakub Kicinski <kuba@kernel.org>2026-08-20 12:58:33 -0700
commitf12c2de4f542e3220e17e0606f492110064f04cb (patch)
treeec4ad290ef6811b2e779e63c6e5a2179aebe8209 /include/linux
parent44930446dde45a7a90fe1446fa38eb0e2c561646 (diff)
batman-adv: reject unrepresentable multicast TVLV offsets
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: 07afe1ba288c ("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>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/skbuff.h24
1 files changed, 24 insertions, 0 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 95184183180f..5522716df8ff 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3126,6 +3126,30 @@ static inline void skb_set_transport_header(struct sk_buff *skb,
skb->transport_header += offset;
}
+/**
+ * skb_set_transport_header_careful - conditionally set transport header
+ * @skb: buffer to alter
+ * @offset: offset to add to skb->data
+ *
+ * Hardened version of skb_set_transport_header().
+ *
+ * Returns: true if the operation was a success.
+ */
+static inline bool __must_check
+skb_set_transport_header_careful(struct sk_buff *skb, const int offset)
+{
+ long thoff = skb->data - skb->head + offset;
+
+ if (unlikely(thoff != (typeof(skb->transport_header))thoff))
+ return false;
+
+ if (unlikely(thoff == (typeof(skb->transport_header))~0U))
+ return false;
+
+ skb->transport_header = thoff;
+ return true;
+}
+
static inline unsigned char *skb_network_header(const struct sk_buff *skb)
{
return skb->head + skb->network_header;