batman-adv: Only read OGM tvlv_len after buffer len check
commit a15d56a60760aa9dbe26343b9a0ac5228f35d445 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: 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
89ea639a2c
commit
28400323ea
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user