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 <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2022-06-01 17:10:11 +02:00
parent f5b2f86ac0
commit c047b50638

View File

@ -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)) {