Commit 7d4201ff authored by Sven Eckelmann's avatar Sven Eckelmann Committed by Greg Kroah-Hartman

batman-adv: Only read OGM2 tvlv_len after buffer len check

[ Upstream commit 0ff0f15a ]

Multiple batadv_ogm2_packet can be stored in an skbuff. The functions
batadv_v_ogm_send_to_if() uses batadv_v_ogm_aggr_packet() to check if there
is another additional batadv_ogm2_packet in the skb or not before they
continue processing the packet.

The length for such an OGM2 is BATADV_OGM2_HLEN +
batadv_ogm2_packet->tvlv_len. The check must first check that at least
BATADV_OGM2_HLEN bytes are available before it accesses tvlv_len (which is
part of the header. Otherwise it might try read outside of the currently
available skbuff to get the content of tvlv_len.

Fixes: 9323158e ("batman-adv: OGMv2 - implement originators logic")
Signed-off-by: default avatarSven Eckelmann <sven@narfation.org>
Signed-off-by: default avatarSimon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 5b8b6627
...@@ -643,17 +643,23 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv, ...@@ -643,17 +643,23 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
* batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated * batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated
* @buff_pos: current position in the skb * @buff_pos: current position in the skb
* @packet_len: total length of the skb * @packet_len: total length of the skb
* @tvlv_len: tvlv length of the previously considered OGM * @ogm2_packet: potential OGM2 in buffer
* *
* Return: true if there is enough space for another OGM, false otherwise. * Return: true if there is enough space for another OGM, false otherwise.
*/ */
static bool batadv_v_ogm_aggr_packet(int buff_pos, int packet_len, static bool
__be16 tvlv_len) batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
const struct batadv_ogm2_packet *ogm2_packet)
{ {
int next_buff_pos = 0; int next_buff_pos = 0;
next_buff_pos += buff_pos + BATADV_OGM2_HLEN; /* check if there is enough space for the header */
next_buff_pos += ntohs(tvlv_len); next_buff_pos += buff_pos + sizeof(*ogm2_packet);
if (next_buff_pos > packet_len)
return false;
/* check if there is enough space for the optional TVLV */
next_buff_pos += ntohs(ogm2_packet->tvlv_len);
return (next_buff_pos <= packet_len) && return (next_buff_pos <= packet_len) &&
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
...@@ -830,7 +836,7 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb, ...@@ -830,7 +836,7 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
ogm_packet = (struct batadv_ogm2_packet *)skb->data; ogm_packet = (struct batadv_ogm2_packet *)skb->data;
while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb), while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
ogm_packet->tvlv_len)) { ogm_packet)) {
batadv_v_ogm_process(skb, ogm_offset, if_incoming); batadv_v_ogm_process(skb, ogm_offset, if_incoming);
ogm_offset += BATADV_OGM2_HLEN; ogm_offset += BATADV_OGM2_HLEN;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment