ospf6d: Fix LSA formatting out-of-bounds access

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>
This commit is contained in:
Martin Buck 2021-01-29 16:40:04 +01:00
parent ecf497baed
commit 100f2989b3

View 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);
}