diff options
author | Sven Eckelmann <sven@narfation.org> | 2019-08-22 02:55:36 -0400 |
---|---|---|
committer | Simon Wunderlich <sw@simonwunderlich.de> | 2019-08-23 12:20:17 -0400 |
commit | a15d56a60760aa9dbe26343b9a0ac5228f35d445 (patch) | |
tree | 1db1303a1b1511df243c7f0dd4a0f8a4e3ec245a | |
parent | 3ee1bb7aae97324ec9078da1f00cb2176919563f (diff) |
batman-adv: Only read OGM tvlv_len after buffer len check
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: ef26157747d4 ("batman-adv: tvlv - basic infrastructure")
Reported-by: syzbot+355cab184197dbbfa384@syzkaller.appspotmail.com
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Acked-by: Antonio Quartulli <a@unstable.cc>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 240ed70912d6..d78938e3e008 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -277,17 +277,23 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv) | |||
277 | * batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached | 277 | * batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached |
278 | * @buff_pos: current position in the skb | 278 | * @buff_pos: current position in the skb |
279 | * @packet_len: total length of the skb | 279 | * @packet_len: total length of the skb |
280 | * @tvlv_len: tvlv length of the previously considered OGM | 280 | * @ogm_packet: potential OGM in buffer |
281 | * | 281 | * |
282 | * Return: true if there is enough space for another OGM, false otherwise. | 282 | * Return: true if there is enough space for another OGM, false otherwise. |
283 | */ | 283 | */ |
284 | static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, | 284 | static bool |
285 | __be16 tvlv_len) | 285 | batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, |
286 | const struct batadv_ogm_packet *ogm_packet) | ||
286 | { | 287 | { |
287 | int next_buff_pos = 0; | 288 | int next_buff_pos = 0; |
288 | 289 | ||
289 | next_buff_pos += buff_pos + BATADV_OGM_HLEN; | 290 | /* check if there is enough space for the header */ |
290 | next_buff_pos += ntohs(tvlv_len); | 291 | next_buff_pos += buff_pos + sizeof(*ogm_packet); |
292 | if (next_buff_pos > packet_len) | ||
293 | return false; | ||
294 | |||
295 | /* check if there is enough space for the optional TVLV */ | ||
296 | next_buff_pos += ntohs(ogm_packet->tvlv_len); | ||
291 | 297 | ||
292 | return (next_buff_pos <= packet_len) && | 298 | return (next_buff_pos <= packet_len) && |
293 | (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); | 299 | (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); |
@@ -315,7 +321,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, | |||
315 | 321 | ||
316 | /* adjust all flags and log packets */ | 322 | /* adjust all flags and log packets */ |
317 | while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, | 323 | while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, |
318 | batadv_ogm_packet->tvlv_len)) { | 324 | batadv_ogm_packet)) { |
319 | /* we might have aggregated direct link packets with an | 325 | /* we might have aggregated direct link packets with an |
320 | * ordinary base packet | 326 | * ordinary base packet |
321 | */ | 327 | */ |
@@ -1704,7 +1710,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, | |||
1704 | 1710 | ||
1705 | /* unpack the aggregated packets and process them one by one */ | 1711 | /* unpack the aggregated packets and process them one by one */ |
1706 | while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb), | 1712 | while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb), |
1707 | ogm_packet->tvlv_len)) { | 1713 | ogm_packet)) { |
1708 | batadv_iv_ogm_process(skb, ogm_offset, if_incoming); | 1714 | batadv_iv_ogm_process(skb, ogm_offset, if_incoming); |
1709 | 1715 | ||
1710 | ogm_offset += BATADV_OGM_HLEN; | 1716 | ogm_offset += BATADV_OGM_HLEN; |