]> git.proxmox.com Git - mirror_frr.git/commitdiff
pimd: Validate the fields before accessing it
authorMobashshera Rasool <mrasool@vmware.com>
Mon, 26 Jul 2021 13:35:31 +0000 (06:35 -0700)
committerMobashshera Rasool <mrasool@vmware.com>
Tue, 27 Jul 2021 09:12:30 +0000 (02:12 -0700)
This commit is to correct the order in which the fields are
accessed while verifying it. First the fields should be
verified, and if it is valid then access it.

Signed-off-by: Mobashshera Rasool <mrasool@vmware.com>
pimd/pim_igmp.c
pimd/pim_igmp.h

index 3325b6ee34989d210024139b1ef98c5ecb2d6dda..426112d4d608d9464b7b98b785350bd12feaa343 100644 (file)
@@ -473,15 +473,33 @@ static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from,
        return 0;
 }
 
-bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, int igmp_msg_len,
-                           int msg_type)
+bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, size_t *hlen)
 {
+       char *igmp_msg;
+       int igmp_msg_len;
+       int msg_type;
+       size_t ip_hlen; /* ip header length in bytes */
+
        if (len < sizeof(*ip_hdr)) {
                zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", len,
                          sizeof(*ip_hdr));
                return false;
        }
 
+       ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
+       *hlen = ip_hlen;
+
+       if (ip_hlen > len) {
+               zlog_warn(
+                       "IGMP packet header claims size %zu, but we only have %zu bytes",
+                       ip_hlen, len);
+               return false;
+       }
+
+       igmp_msg = (char *)ip_hdr + ip_hlen;
+       igmp_msg_len = len - ip_hlen;
+       msg_type = *igmp_msg;
+
        if (igmp_msg_len < PIM_IGMP_MIN_LEN) {
                zlog_warn("IGMP message size=%d shorter than minimum=%d",
                          igmp_msg_len, PIM_IGMP_MIN_LEN);
@@ -514,7 +532,7 @@ bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, int igmp_msg_len,
 
 int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
 {
-       struct ip *ip_hdr;
+       struct ip *ip_hdr = (struct ip *)buf;
        size_t ip_hlen; /* ip header length in bytes */
        char *igmp_msg;
        int igmp_msg_len;
@@ -522,16 +540,8 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
        char from_str[INET_ADDRSTRLEN];
        char to_str[INET_ADDRSTRLEN];
 
-       ip_hdr = (struct ip *)buf;
-
-       ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
-
-       if (ip_hlen > len) {
-               zlog_warn(
-                       "IGMP packet header claims size %zu, but we only have %zu bytes",
-                       ip_hlen, len);
+       if (!pim_igmp_verify_header(ip_hdr, len, &ip_hlen))
                return -1;
-       }
 
        igmp_msg = buf + ip_hlen;
        igmp_msg_len = len - ip_hlen;
@@ -547,14 +557,6 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
                        msg_type, igmp_msg_len);
        }
 
-       if (!pim_igmp_verify_header(ip_hdr, len, igmp_msg_len, msg_type)) {
-               zlog_warn(
-                       "Recv IGMP packet from %s to %s on %s: size=%zu ttl=%u msg_type=%d msg_size=%d",
-                       from_str, to_str, igmp->interface->name, len,
-                       ip_hdr->ip_ttl, msg_type, igmp_msg_len);
-               return -1;
-       }
-
        switch (msg_type) {
        case PIM_IGMP_MEMBERSHIP_QUERY: {
                int max_resp_code = igmp_msg[1];
index 01bf02da9f3c50990d4eb507a28f8957c7c3b749..abb8af836b49802ba1a5f7ab69de321aaa9c16b6 100644 (file)
@@ -116,8 +116,7 @@ void igmp_sock_delete(struct igmp_sock *igmp);
 void igmp_sock_free(struct igmp_sock *igmp);
 void igmp_sock_delete_all(struct interface *ifp);
 int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len);
-bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, int igmp_msg_len,
-                           int msg_type);
+bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, size_t *ip_hlen);
 void pim_igmp_general_query_on(struct igmp_sock *igmp);
 void pim_igmp_general_query_off(struct igmp_sock *igmp);
 void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp);