]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: fix MSDP crash on unexpected TLV sizes
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Wed, 7 Dec 2022 14:48:47 +0000 (11:48 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Wed, 7 Dec 2022 14:48:47 +0000 (11:48 -0300)
Increase the MSDP peer stream buffer size to handle the whole TLV
(maximum is 65KiB due to 16bit field). If the stream is not resized
there will be a crash in the read function attempting to put more than
9192 (`PIM_MSDP_SA_TLV_MAX_SIZE`) bytes.

According to the RFC 3618 Section 12 we should accept the TLV and we
should not reset the peer connection.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
pimd/pim_msdp_packet.c

index 1152dd6f674526ec8701869a4092ff3908456d7c..9f0cba03c2cd389a1a18f7af142e7356d8f23d2b 100644 (file)
@@ -711,6 +711,30 @@ void pim_msdp_read(struct thread *thread)
                        pim_msdp_pkt_rxed_with_fatal_error(mp);
                        return;
                }
+
+               /*
+                * Handle messages with longer than expected TLV size: resize
+                * the stream to handle reading the whole message.
+                *
+                * RFC 3618 Section 12. 'Packet Formats':
+                * > ... If an implementation receives a TLV whose length
+                * > exceeds the maximum TLV length specified below, the TLV
+                * > SHOULD be accepted. Any additional data, including possible
+                * > next TLV's in the same message, SHOULD be ignored, and the
+                * > MSDP session should not be reset. ...
+                */
+               if (len > PIM_MSDP_SA_TLV_MAX_SIZE) {
+                       /* Check if the current buffer is big enough. */
+                       if (mp->ibuf->size < len) {
+                               if (PIM_DEBUG_MSDP_PACKETS)
+                                       zlog_debug(
+                                               "MSDP peer %s sent TLV with unexpected large length (%d bytes)",
+                                               mp->key_str, len);
+
+                               stream_resize_inplace(&mp->ibuf, len);
+                       }
+               }
+
                /* read complete TLV */
                mp->packet_size = len;
        }