diff options
author | Quentin Young <qlyoung@cumulusnetworks.com> | 2020-04-14 06:39:15 +0200 |
---|---|---|
committer | Quentin Young <qlyoung@cumulusnetworks.com> | 2020-04-14 17:29:10 +0200 |
commit | 04d6a0f823e20c5e1d5f42042a8eefd5f5a76924 (patch) | |
tree | a12eb7041af4a12edbddfdad12260140e46d841e /ospfd/ospf_packet.c | |
parent | Merge pull request #6213 from ton31337/fix/moar_bool_stuff (diff) | |
download | frr-04d6a0f823e20c5e1d5f42042a8eefd5f5a76924.tar.xz frr-04d6a0f823e20c5e1d5f42042a8eefd5f5a76924.zip |
ospfd: router LSA link info missing length check
Fix
- Modulo check on data length not inclusive enough
- Garbage heap read when bounds checking
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'ospfd/ospf_packet.c')
-rw-r--r-- | ospfd/ospf_packet.c | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index aa50aeacb..49d80b747 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -2604,7 +2604,7 @@ static unsigned ospf_router_lsa_links_examin(struct router_lsa_link *link, { unsigned counted_links = 0, thislinklen; - while (linkbytes) { + while (linkbytes >= OSPF_ROUTER_LSA_LINK_SIZE) { thislinklen = OSPF_ROUTER_LSA_LINK_SIZE + 4 * link->m[0].tos_count; if (thislinklen > linkbytes) { @@ -2642,26 +2642,32 @@ static unsigned ospf_lsa_examin(struct lsa_header *lsah, const uint16_t lsalen, return MSG_NG; } switch (lsah->type) { - case OSPF_ROUTER_LSA: - /* RFC2328 A.4.2, LSA header + 4 bytes followed by N>=1 - * (12+)-byte link blocks */ - if (headeronly) { - ret = (lsalen - OSPF_LSA_HEADER_SIZE - - OSPF_ROUTER_LSA_MIN_SIZE) - % 4 - ? MSG_NG - : MSG_OK; - break; - } + case OSPF_ROUTER_LSA: { + /* + * RFC2328 A.4.2, LSA header + 4 bytes followed by N>=0 + * (12+)-byte link blocks + */ + size_t linkbytes_len = lsalen - OSPF_LSA_HEADER_SIZE + - OSPF_ROUTER_LSA_MIN_SIZE; + + /* + * LSA link blocks are variable length but always multiples of + * 4; basic sanity check + */ + if (linkbytes_len % 4 != 0) + return MSG_NG; + + if (headeronly) + return MSG_OK; + rlsa = (struct router_lsa *)lsah; + ret = ospf_router_lsa_links_examin( (struct router_lsa_link *)rlsa->link, - lsalen - OSPF_LSA_HEADER_SIZE - 4, /* skip: basic - header, "flags", - 0, "# links" */ - ntohs(rlsa->links) /* 16 bits */ - ); + linkbytes_len, + ntohs(rlsa->links)); break; + } case OSPF_AS_EXTERNAL_LSA: /* RFC2328 A.4.5, LSA header + 4 bytes followed by N>=1 12-bytes long * blocks */ |