]> git.puffer.fish Git - matthieu/frr.git/commitdiff
eigrpd: validate TLV lengths
authorMark Stapp <mjs@voltanet.io>
Mon, 26 Apr 2021 15:20:57 +0000 (11:20 -0400)
committerMark Stapp <mjs@voltanet.io>
Mon, 26 Apr 2021 15:20:57 +0000 (11:20 -0400)
Check that incoming TLVS a) don't overrun the incoming packet,
b) don't underrun the required size for the type of TLV.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
eigrpd/eigrp_hello.c

index 13a2c4206fbe73f8004970ecea772aed22f32fb3..e3680b31a33ffd745abd935b29eb2c4b05a49ac0 100644 (file)
@@ -125,6 +125,10 @@ eigrp_hello_parameter_decode(struct eigrp_neighbor *nbr,
        struct eigrp *eigrp = nbr->ei->eigrp;
        struct TLV_Parameter_Type *param = (struct TLV_Parameter_Type *)tlv;
 
+       /* First validate TLV length */
+       if (tlv->length < sizeof(struct TLV_Parameter_Type))
+               return NULL;
+
        /* copy over the values passed in by the neighbor */
        nbr->K1 = param->K1;
        nbr->K2 = param->K2;
@@ -194,13 +198,22 @@ eigrp_hello_authentication_decode(struct stream *s,
 
        md5 = (struct TLV_MD5_Authentication_Type *)tlv_header;
 
-       if (md5->auth_type == EIGRP_AUTH_TYPE_MD5)
+       if (md5->auth_type == EIGRP_AUTH_TYPE_MD5) {
+               /* Validate tlv length */
+               if (md5->length < sizeof(struct TLV_MD5_Authentication_Type))
+                       return 0;
+
                return eigrp_check_md5_digest(s, md5, nbr,
                                              EIGRP_AUTH_BASIC_HELLO_FLAG);
-       else if (md5->auth_type == EIGRP_AUTH_TYPE_SHA256)
+       } else if (md5->auth_type == EIGRP_AUTH_TYPE_SHA256) {
+               /* Validate tlv length */
+               if (md5->length < sizeof(struct TLV_SHA256_Authentication_Type))
+                       return 0;
+
                return eigrp_check_sha256_digest(
                        s, (struct TLV_SHA256_Authentication_Type *)tlv_header,
                        nbr, EIGRP_AUTH_BASIC_HELLO_FLAG);
+       }
 
        return 0;
 }
@@ -223,6 +236,10 @@ static void eigrp_sw_version_decode(struct eigrp_neighbor *nbr,
 {
        struct TLV_Software_Type *version = (struct TLV_Software_Type *)tlv;
 
+       /* Validate TLV length */
+       if (tlv->length < sizeof(struct TLV_Software_Type))
+               return;
+
        nbr->os_rel_major = version->vender_major;
        nbr->os_rel_minor = version->vender_minor;
        nbr->tlv_rel_major = version->eigrp_major;
@@ -250,6 +267,10 @@ static void eigrp_peer_termination_decode(struct eigrp_neighbor *nbr,
        struct TLV_Peer_Termination_type *param =
                (struct TLV_Peer_Termination_type *)tlv;
 
+       /* Validate TLV length */
+       if (tlv->length < sizeof(struct TLV_Peer_Termination_type))
+               return;
+
        uint32_t my_ip = nbr->ei->address.u.prefix4.s_addr;
        uint32_t received_ip = param->neighbor_ip;
 
@@ -346,6 +367,10 @@ void eigrp_hello_receive(struct eigrp *eigrp, struct ip *iph,
                type = ntohs(tlv_header->type);
                length = ntohs(tlv_header->length);
 
+               /* Validate length against packet size */
+               if (length > size)
+                       return;
+
                if ((length > 0) && (length <= size)) {
                        if (IS_DEBUG_EIGRP_PACKET(0, RECV))
                                zlog_debug(