]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospf6d: fix rx/tx buffer sizes 11329/head
authorDavid Lamparter <equinox@opensourcerouting.org>
Wed, 1 Jun 2022 15:10:11 +0000 (17:10 +0200)
committerDavid Lamparter <equinox@opensourcerouting.org>
Wed, 1 Jun 2022 15:10:11 +0000 (17:10 +0200)
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>
ospf6d/ospf6_message.c

index ae7f16a9f61ebdc951a6e1db51da65beced7a8be..93a062b215f5f1f9d81d026d8d95019dff42eae6 100644 (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)) {