]> 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)
committerIgor Ryzhov <iryzhov@nfware.com>
Tue, 16 Feb 2021 18:03:31 +0000 (21:03 +0300)
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 6a7a7ac75164726a27ff4247ba2c661c363d09c2..909b7a6f597a3fa7b14ccb584c364ad50661e6f0 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,
@@ -604,7 +605,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) {
@@ -622,7 +623,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;
 }
@@ -805,7 +806,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) {
@@ -825,7 +826,7 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
                                        prefix->prefix_length);
                                return (buf);
                        }
-               } while (current <= end);
+               }
        }
        return NULL;
 }