--- /dev/null
+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
+
+diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
+index 7bfd0d7ef49df8e699f91e2b827b824aa3657c0d..5afc4e9646d622c6f924d4610ac58eb77404b37a 100644
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -450,17 +450,23 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
+ * 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);
+@@ -488,7 +494,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
+
+ /* 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
+ */
+@@ -1838,7 +1844,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
+
+ /* 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;