From d765574fdb1c4ee05150da04d2d06ddfcddb3c93 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 7 Jun 2022 23:49:17 -0400 Subject: [PATCH] freebsd_network: Adjust too-large packet handling in read(). Before ca6a44c1333c467706a7ceae2842d0de380139cb, this function returned whatever amount of the buffer it could and silently discarded the rest. After that change and before this one, it would refuse to return anything, which meant that as soon as we got one packet too large to handle, we would never receive any more packets (and the errors displayed in e.g. ifconfig would go up forever.) Now, we discard too-large packets so RX will not stall completely and still return E2BIG (so error counts will go up), but we also print an error to syslog, so that precisely what has gone wrong will be easily known. --- src/libs/compat/freebsd_network/device_hooks.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/libs/compat/freebsd_network/device_hooks.c b/src/libs/compat/freebsd_network/device_hooks.c index 9389a6b99e..4ab25af2f0 100644 --- a/src/libs/compat/freebsd_network/device_hooks.c +++ b/src/libs/compat/freebsd_network/device_hooks.c @@ -134,16 +134,17 @@ compat_read(void *cookie, off_t position, void *buffer, size_t *numBytes) } else if (status < B_OK) return status; - IF_LOCK(&ifp->receive_queue); - if (ifp->receive_queue.ifq_head != NULL - && ifp->receive_queue.ifq_head->m_pkthdr.len >= length) { - IF_UNLOCK(&ifp->receive_queue); - return E2BIG; - } - _IF_DEQUEUE(&ifp->receive_queue, mb); - IF_UNLOCK(&ifp->receive_queue); + IF_DEQUEUE(&ifp->receive_queue, mb); } while (mb == NULL); + if (mb->m_pkthdr.len > length) { + if_printf(ifp, "error reading packet: too large! (%d > %" B_PRIuSIZE ")\n", + mb->m_pkthdr.len, length); + m_freem(mb); + *numBytes = 0; + return E2BIG; + } + length = min_c(max_c((size_t)mb->m_pkthdr.len, 0), length); m_copydata(mb, 0, length, buffer);