73 lines
2.9 KiB
Diff
73 lines
2.9 KiB
Diff
From: Sven Eckelmann <sven@narfation.org>
|
|
Date: Fri, 23 Aug 2019 14:34:27 +0200
|
|
Subject: 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: 0b6aa0d43767 ("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>
|
|
|
|
Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/07b6051ebcfaa7ea89b4f278eca2ff4070d29e56
|
|
|
|
--- 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, cons
|
|
* batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached
|
|
* @buff_pos: current position in the skb
|
|
* @packet_len: total length of the skb
|
|
- * @tvlv_len: tvlv length of the previously considered OGM
|
|
+ * @ogm_packet: potential OGM in buffer
|
|
*
|
|
* Return: true if there is enough space for another OGM, false otherwise.
|
|
*/
|
|
-static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
|
|
- __be16 tvlv_len)
|
|
+static bool
|
|
+batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
|
|
+ const struct batadv_ogm_packet *ogm_packet)
|
|
{
|
|
int next_buff_pos = 0;
|
|
|
|
- next_buff_pos += buff_pos + BATADV_OGM_HLEN;
|
|
- next_buff_pos += ntohs(tvlv_len);
|
|
+ /* check if there is enough space for the header */
|
|
+ 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) &&
|
|
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
|
|
@@ -315,7 +321,7 @@ static void batadv_iv_ogm_send_to_if(str
|
|
|
|
/* adjust all flags and log packets */
|
|
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
|
|
* ordinary base packet
|
|
*/
|
|
@@ -1704,7 +1710,7 @@ static int batadv_iv_ogm_receive(struct
|
|
|
|
/* unpack the aggregated packets and process them one by one */
|
|
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);
|
|
|
|
ogm_offset += BATADV_OGM_HLEN;
|