From c047b50638fd4bd9c5990ae0abf8195598c1929f Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 1 Jun 2022 17:10:11 +0200 Subject: [PATCH] ospf6d: fix rx/tx buffer sizes OSPFv3 packets can be fragmented and up to 64k long, regardless of interface MTU. Trying to size these buffers to MTU is just plain wrong. To not make this a super intrusive change during the 8.3 release freeze, just code this into ospf6_iobuf_size(). Since the buffer is now always 64k, don't waste time zeroing the entire thing in receive; instead just zero kind of a "sled" of 128 bytes after the buffer as a security precaution. Fixes: #11298 Signed-off-by: David Lamparter --- ospf6d/ospf6_message.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) 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)) { -- 2.39.5