Commit 1457fb5c authored by Sven Eckelmann's avatar Sven Eckelmann Committed by Kelsey Skunberg

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

BugLink: https://bugs.launchpad.net/bugs/1868629

commit a15d56a6 upstream.

Multiple batadv_ogm_packet can be stored in an skbuff. The functions
batadv_iv_ogm_send_to_if()/batadv_iv_ogm_receive() use
batadv_iv_ogm_aggr_packet() to check if there is another additional
batadv_ogm_packet in the skb or not before they continue processing the
packet.

The length for such an OGM is BATADV_OGM_HLEN +
batadv_ogm_packet->tvlv_len. The check must first check that at least
BATADV_OGM_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: ef261577 ("batman-adv: tvlv - basic infrastructure")
Reported-by: syzbot+355cab184197dbbfa384@syzkaller.appspotmail.com
Signed-off-by: default avatarSven Eckelmann <sven@narfation.org>
Acked-by: default avatarAntonio Quartulli <a@unstable.cc>
Signed-off-by: default avatarSimon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
Signed-off-by: default avatarKelsey Skunberg <kelsey.skunberg@canonical.com>
parent a2a72c15
...@@ -397,14 +397,19 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv) ...@@ -397,14 +397,19 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
return new_tq; return new_tq;
} }
/* is there another aggregated packet here? */ static bool
static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
__be16 tvlv_len) const struct batadv_ogm_packet *ogm_packet)
{ {
int next_buff_pos = 0; int next_buff_pos = 0;
next_buff_pos += buff_pos + BATADV_OGM_HLEN; /* check if there is enough space for the header */
next_buff_pos += ntohs(tvlv_len); next_buff_pos += buff_pos + sizeof(*ogm_packet);
if (next_buff_pos > packet_len)
return false;
/* check if there is enough space for the optional TVLV */
next_buff_pos += ntohs(ogm_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);
...@@ -432,7 +437,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, ...@@ -432,7 +437,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
/* adjust all flags and log packets */ /* adjust all flags and log packets */
while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
batadv_ogm_packet->tvlv_len)) { batadv_ogm_packet)) {
/* we might have aggregated direct link packets with an /* we might have aggregated direct link packets with an
* ordinary base packet * ordinary base packet
*/ */
...@@ -1751,7 +1756,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, ...@@ -1751,7 +1756,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
/* unpack the aggregated packets and process them one by one */ /* unpack the aggregated packets and process them one by one */
while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb), while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
ogm_packet->tvlv_len)) { ogm_packet)) {
batadv_iv_ogm_process(skb, ogm_offset, if_incoming); batadv_iv_ogm_process(skb, ogm_offset, if_incoming);
ogm_offset += BATADV_OGM_HLEN; ogm_offset += BATADV_OGM_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