]> git.proxmox.com Git - mirror_frr.git/commitdiff
ospf6d: Fix LSA formatting out-of-bounds access
authorMartin Buck <mb-tmp-tvguho.pbz@gromit.dyndns.org>
Fri, 29 Jan 2021 15:40:04 +0000 (16:40 +0100)
committerMartin Buck <mb-tmp-tvguho.pbz@gromit.dyndns.org>
Fri, 29 Jan 2021 18:38:17 +0000 (19:38 +0100)
Check whether full struct ospf6_router_lsdesc/ospf6_prefix is accessible
before accessing its contents. Previously, we only checked for the first
byte in ospf6_router_lsa_get_nbr_id() or not even that (due to an additional
off-by-one error) in ospf6_link_lsa_get_prefix_str() and
ospf6_intra_prefix_lsa_get_prefix_str().

Also check *before* accessing the first prefix instead of starting the
checks only at the 2nd prefix.

The previous code could cause out-of-bounds accesses with valid LSAs in case
of ospf6_link_lsa_get_prefix_str() and
ospf6_intra_prefix_lsa_get_prefix_str() and with specially crafted LSAs
(bad length field) in case of ospf6_router_lsa_get_nbr_id().

Signed-off-by: Martin Buck <mb-tmp-tvguho.pbz@gromit.dyndns.org>
ospf6d/ospf6_intra.c

index 01e4b31c4ef4b44c9048a7a433e9f2c98d638156..a8a469136d09889aa958c6f525c80702ef8ea34a 100644 (file)
@@ -76,7 +76,8 @@ static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf,
                                  *)(start
                                     + pos * (sizeof(struct
                                                     ospf6_router_lsdesc)));
-               if ((char *)lsdesc < end) {
+               if ((char *)lsdesc + sizeof(struct ospf6_router_lsdesc)
+                   <= end) {
                        if (buf && (buflen > INET_ADDRSTRLEN * 2)) {
                                inet_ntop(AF_INET,
                                          &lsdesc->neighbor_interface_id, buf1,
@@ -650,7 +651,7 @@ static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf,
                end = (char *)lsa->header + ntohs(lsa->header->length);
                current = start;
 
-               do {
+               while (current + sizeof(struct ospf6_prefix) <= end) {
                        prefix = (struct ospf6_prefix *)current;
                        if (prefix->prefix_length == 0
                            || current + OSPF6_PREFIX_SIZE(prefix) > end) {
@@ -668,7 +669,7 @@ static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf,
                                inet_ntop(AF_INET6, &in6, buf, buflen);
                                return (buf);
                        }
-               } while (current <= end);
+               }
        }
        return NULL;
 }
@@ -879,7 +880,7 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
                end = (char *)lsa->header + ntohs(lsa->header->length);
                current = start;
 
-               do {
+               while (current + sizeof(struct ospf6_prefix) <= end) {
                        prefix = (struct ospf6_prefix *)current;
                        if (prefix->prefix_length == 0
                            || current + OSPF6_PREFIX_SIZE(prefix) > end) {
@@ -899,7 +900,7 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
                                        prefix->prefix_length);
                                return (buf);
                        }
-               } while (current <= end);
+               }
        }
        return (buf);
 }