diff options
| author | Martin Buck <mb-tmp-tvguho.pbz@gromit.dyndns.org> | 2021-01-29 16:40:04 +0100 | 
|---|---|---|
| committer | Martin Buck <mb-tmp-tvguho.pbz@gromit.dyndns.org> | 2021-01-29 19:38:17 +0100 | 
| commit | 100f2989b351d337a28742a69e82e4b4b5e16ba0 (patch) | |
| tree | 1d35a9927eb82b60e109cde29c4b8887bb605ad2 /ospf6d | |
| parent | ecf497baeda77bfd040818c7bd2ad412cac76d66 (diff) | |
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>
Diffstat (limited to 'ospf6d')
| -rw-r--r-- | ospf6d/ospf6_intra.c | 11 | 
1 files changed, 6 insertions, 5 deletions
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 01e4b31c4e..a8a469136d 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -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);  }  | 
