summaryrefslogtreecommitdiffstats
path: root/ospfd/ospf_packet.c
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2020-04-14 06:39:15 +0200
committerQuentin Young <qlyoung@cumulusnetworks.com>2020-04-14 17:29:10 +0200
commit04d6a0f823e20c5e1d5f42042a8eefd5f5a76924 (patch)
treea12eb7041af4a12edbddfdad12260140e46d841e /ospfd/ospf_packet.c
parentMerge pull request #6213 from ton31337/fix/moar_bool_stuff (diff)
downloadfrr-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.c40
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 */