summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMobashshera Rasool <mrasool@vmware.com>2021-07-26 06:35:31 -0700
committerMobashshera Rasool <mrasool@vmware.com>2021-07-27 02:12:30 -0700
commit88ea79ad94389a920811bdfffe115082bcd021ea (patch)
tree65572a76976191df90da6603fd402d9524d4809a
parent53d7080980bb4e3bf6ef053673ebc560c5412103 (diff)
pimd: Validate the fields before accessing it
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>
-rw-r--r--pimd/pim_igmp.c42
-rw-r--r--pimd/pim_igmp.h3
2 files changed, 23 insertions, 22 deletions
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index 3325b6ee34..426112d4d6 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -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];
diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h
index 01bf02da9f..abb8af836b 100644
--- a/pimd/pim_igmp.h
+++ b/pimd/pim_igmp.h
@@ -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);