diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index ae7f16a9f6..93a062b215 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -1733,19 +1733,22 @@ static unsigned int iobuflen = 0; int ospf6_iobuf_size(unsigned int size) { - uint8_t *recvnew, *sendnew; + /* NB: there was previously code here that tried to dynamically size + * the buffer for whatever we see in MTU on interfaces. Which is + * _unconditionally wrong_ - we can always receive fragmented IPv6 + * up to the regular 64k length limit. (No jumbograms, thankfully.) + */ - if (size <= iobuflen) - return iobuflen; + if (!iobuflen) { + /* the + 128 is to have some runway at the end */ + size_t alloc_size = 65536 + 128; - recvnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size); - sendnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size); + assert(!recvbuf && !sendbuf); - XFREE(MTYPE_OSPF6_MESSAGE, recvbuf); - XFREE(MTYPE_OSPF6_MESSAGE, sendbuf); - recvbuf = recvnew; - sendbuf = sendnew; - iobuflen = size; + recvbuf = XMALLOC(MTYPE_OSPF6_MESSAGE, alloc_size); + sendbuf = XMALLOC(MTYPE_OSPF6_MESSAGE, alloc_size); + iobuflen = alloc_size; + } return iobuflen; } @@ -1779,7 +1782,6 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6) memset(&src, 0, sizeof(src)); memset(&dst, 0, sizeof(dst)); ifindex = 0; - memset(recvbuf, 0, iobuflen); iovector[0].iov_base = recvbuf; iovector[0].iov_len = iobuflen; iovector[1].iov_base = NULL; @@ -1795,6 +1797,9 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6) return OSPF6_READ_ERROR; } + /* ensure some zeroes past the end, just as a security precaution */ + memset(recvbuf + len, 0, MIN(128, iobuflen - len)); + oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id); if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {