* [PATCH 0/4] net: Consistently pad short packets for all backends
@ 2026-10-27 17:46 Peter Maydell
2026-10-27 17:46 ` [PATCH 1/4] tests/qtest: Make netfilter tests accept padded ethernet packets Peter Maydell
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Peter Maydell @ 2026-10-27 17:46 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Fleytman, Akihiko Odaki, Jason Wang, Samuel Thibault,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
Daniel P. Berrangé, Zhang Chen, Li Zhijian
The net core code design is that by default packets are padded out to
the ethernet frame minimum before being handed to a network device
model, unless that device explicitly opted in by setting do_not_pad.
This avoids a whole class of bugs where network device receive code
has to be very careful about handling short packets.
However, at the moment we do this check manually in the network
backend code before it calls qemu_send_packet() or
qemu_send_packet_async(), and we forgot to do it in all backends. So
you get the padding for the slirp, tap and vmnet backends, but not
for the "minor" backends like 'passt', 'socket' and 'dgram', or if
you configure two network devices connected by an emulated hub.
This series fixes this by moving the padding code to
qemu_send_packet()/qemu_sendv_packet(), so that it always happens
regardless of the backend.
The main bug this is fixing is
https://gitlab.com/qemu-project/qemu/-/work_items/2362
but it's been re-reported multiple times for various combinations
of network devices and backends.
The whole series is cc stable because without the padding you can
provoke various bugs in different network device models.
thanks
-- PMM
Peter Maydell (4):
tests/qtest: Make netfilter tests accept padded ethernet packets
net: Set do_not_pad for net backends
net: Pad short packets in qemu_send_packet and qemu_sendv_packet
net: Remove padding code from net backends
include/net/eth.h | 22 +++++++++++++++++++
include/net/net.h | 3 ++-
net/eth.c | 18 ++++++++++++++++
net/net.c | 32 ++++++++++++++++++++++++----
net/slirp.c | 9 --------
net/tap-win32.c | 15 ++-----------
net/tap.c | 11 +---------
tests/qtest/test-filter-buffer.c | 4 +++-
tests/qtest/test-filter-mirror.c | 4 +++-
tests/qtest/test-filter-redirector.c | 4 +++-
net/vmnet-common.m | 11 ----------
11 files changed, 82 insertions(+), 51 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] tests/qtest: Make netfilter tests accept padded ethernet packets
2026-10-27 17:46 [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
@ 2026-10-27 17:46 ` Peter Maydell
2026-10-28 13:29 ` Fabiano Rosas
2026-10-27 17:46 ` [PATCH 2/4] net: Set do_not_pad for net backends Peter Maydell
` (4 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Peter Maydell @ 2026-10-27 17:46 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Fleytman, Akihiko Odaki, Jason Wang, Samuel Thibault,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
Daniel P. Berrangé, Zhang Chen, Li Zhijian
Currently the various netfilter tests assume and assert that the data
they get from the filter is an exact match for the data that they
send in to it via the net socket backend. This happens to be the
case currently because the net socket backend fails to pad frames to
the ethernet minimum when the device expects that (unlike e.g. the
tap backend). When we fix the socket backend to honour the device's
request for padding, the netfilter will see padded packets for
devices that require them (which is most of them), and not for those
that don't (notably virtio-net).
This seems best considered as a test error: if you're using netfilter
to look at what a particular network device is receiving, you want to
actually see what it is receiving. And most real-world users of
filtering will be doing it with the backends like TAP that were
already doing pad-before-filter; it's only the oddball backends like
'socket' that forgot to pad.
Make the test cases accept as valid both padded and unpadded frames.
Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
tests/qtest/test-filter-buffer.c | 4 +++-
tests/qtest/test-filter-mirror.c | 4 +++-
tests/qtest/test-filter-redirector.c | 4 +++-
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/tests/qtest/test-filter-buffer.c b/tests/qtest/test-filter-buffer.c
index 441cbb975ca..418caccf00a 100644
--- a/tests/qtest/test-filter-buffer.c
+++ b/tests/qtest/test-filter-buffer.c
@@ -11,6 +11,7 @@
#include "qobject/qdict.h"
#include "qemu/iov.h"
#include "qemu/sockets.h"
+#include "net/eth.h"
/*
* Test that changing interval at runtime affects packet release timing.
@@ -148,7 +149,8 @@ static void test_change_interval_timer(void)
ret = recv(recv_sock, &len, sizeof(len), 0);
g_assert_cmpint(ret, ==, sizeof(len));
len = ntohl(len);
- g_assert_cmpint(len, ==, sizeof(send_buf));
+ /* The snooped network device might or might not have asked for padding */
+ g_assert(len == sizeof(send_buf) || len == MAX(sizeof(send_buf), ETH_ZLEN));
ret = recv(recv_sock, recv_buf, len, 0);
g_assert_cmpint(ret, ==, len);
diff --git a/tests/qtest/test-filter-mirror.c b/tests/qtest/test-filter-mirror.c
index 723d2c2f291..9972712cb49 100644
--- a/tests/qtest/test-filter-mirror.c
+++ b/tests/qtest/test-filter-mirror.c
@@ -15,6 +15,7 @@
#include "qemu/sockets.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
+#include "net/eth.h"
static void test_mirror(void)
{
@@ -58,7 +59,8 @@ static void test_mirror(void)
g_assert_cmpint(ret, ==, sizeof(len));
len = ntohl(len);
- g_assert_cmpint(len, ==, sizeof(send_buf));
+ /* The snooped network device might or might not have asked for padding */
+ g_assert(len == sizeof(send_buf) || len == MAX(sizeof(send_buf), ETH_ZLEN));
recv_buf = g_malloc(len);
ret = recv(recv_sock[0], recv_buf, len, 0);
g_assert_cmpint(ret, ==, len);
diff --git a/tests/qtest/test-filter-redirector.c b/tests/qtest/test-filter-redirector.c
index 5540c232c0b..a4f9b73c72a 100644
--- a/tests/qtest/test-filter-redirector.c
+++ b/tests/qtest/test-filter-redirector.c
@@ -57,6 +57,7 @@
#include "qemu/sockets.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
+#include "net/eth.h"
static void test_redirector_tx(void)
{
@@ -115,7 +116,8 @@ static void test_redirector_tx(void)
g_assert_cmpint(ret, ==, sizeof(len));
len = ntohl(len);
- g_assert_cmpint(len, ==, sizeof(send_buf));
+ /* The snooped network device might or might not have asked for padding */
+ g_assert(len == sizeof(send_buf) || len == MAX(sizeof(send_buf), ETH_ZLEN));
recv_buf = g_malloc(len);
ret = recv(recv_sock, recv_buf, len, 0);
g_assert_cmpint(ret, ==, len);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] net: Set do_not_pad for net backends
2026-10-27 17:46 [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
2026-10-27 17:46 ` [PATCH 1/4] tests/qtest: Make netfilter tests accept padded ethernet packets Peter Maydell
@ 2026-10-27 17:46 ` Peter Maydell
2026-10-27 17:46 ` [PATCH 3/4] net: Pad short packets in qemu_send_packet and qemu_sendv_packet Peter Maydell
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2026-10-27 17:46 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Fleytman, Akihiko Odaki, Jason Wang, Samuel Thibault,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
Daniel P. Berrangé, Zhang Chen, Li Zhijian
Currently our handling of short network packets (i.e. those which
are smaller than the minimum ethernet frame size of 60 bytes) is a
little confused. The intention is that we allow network device
models to transmit short packets, but we protect them from having to
deal with receiving short packets unless they explicitly opt into it.
This means we don't have to have a lot of code in each network device
to try to handle the short packet size -- historically that code was
untested, and often a source of "carefully crafted packet can cause
an out-of-bounds memory access" bugs.
Our implementation of the padding is currently done when each network
backend feeds a packet into the system via one of the
qemu_send_packet family of functions. This mostly works, except that
we missed some of the more obscure backends (e.g. the socket
backend), and it means code duplication in each backend. We'd like
to switch to making qemu_send_packet do the padding itself. To do
that, we first need to make sure that all the NetClientState
implementations which do not want padding set the do_not_pad flag.
We do this by setting the flag for NetClientState instances created
by qemu_new_net_client() and qemu_new_net_control_client(). Emulated
network devices use qemu_new_nic(), which does not set the flag.
Note that this also causes the net/hub client to request no padding.
This is the right behaviour: we want the hub to accept short packets
and forward them on to all destinations. Each destination then gets
to choose whether it sees a padded packet or the short one. The
hub.c code is length-agnostic and doesn't look inside the packets it
is passing on, so it has no issues with short packets.
Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/net/net.h | 3 ++-
net/net.c | 10 ++++++----
net/tap.c | 2 +-
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/include/net/net.h b/include/net/net.h
index fdf6a2ddd44..3c5b99c806e 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -169,7 +169,8 @@ void qemu_net_client_setup(NetClientState *nc,
const char *model,
const char *name,
NetClientDestructor *destructor,
- bool is_datapath);
+ bool is_datapath,
+ bool do_not_pad);
NetClientState *qemu_new_net_client(NetClientInfo *info,
NetClientState *peer,
const char *model,
diff --git a/net/net.c b/net/net.c
index d7fa637ce51..1042a9d3a8e 100644
--- a/net/net.c
+++ b/net/net.c
@@ -267,7 +267,8 @@ void qemu_net_client_setup(NetClientState *nc,
const char *model,
const char *name,
NetClientDestructor *destructor,
- bool is_datapath)
+ bool is_datapath,
+ bool do_not_pad)
{
nc->info = info;
nc->model = g_strdup(model);
@@ -287,6 +288,7 @@ void qemu_net_client_setup(NetClientState *nc,
nc->incoming_queue = qemu_new_net_queue(qemu_deliver_packet_iov, nc);
nc->destructor = destructor;
nc->is_datapath = is_datapath;
+ nc->do_not_pad = do_not_pad;
QTAILQ_INIT(&nc->filters);
}
@@ -301,7 +303,7 @@ NetClientState *qemu_new_net_client(NetClientInfo *info,
nc = g_malloc0(info->size);
qemu_net_client_setup(nc, info, peer, model, name,
- qemu_net_client_destructor, true);
+ qemu_net_client_destructor, true, true);
return nc;
}
@@ -317,7 +319,7 @@ NetClientState *qemu_new_net_control_client(NetClientInfo *info,
nc = g_malloc0(info->size);
qemu_net_client_setup(nc, info, peer, model, name,
- qemu_net_client_destructor, false);
+ qemu_net_client_destructor, false, true);
return nc;
}
@@ -344,7 +346,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
for (i = 0; i < queues; i++) {
qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
- NULL, true);
+ NULL, true, false);
nic->ncs[i].queue_index = i;
}
diff --git a/net/tap.c b/net/tap.c
index d71e3dd1175..ada69a21021 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -620,7 +620,7 @@ static TAPState *new_tap(NetClientState *peer,
TAPState *s = TAP_NETDEV(object_new(TYPE_TAP_NETDEV));
qemu_net_client_setup(&s->nc, &net_tap_info, peer, model, name,
- tap_net_client_destructor, true);
+ tap_net_client_destructor, true, true);
s->queue_index = queue_index;
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] net: Pad short packets in qemu_send_packet and qemu_sendv_packet
2026-10-27 17:46 [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
2026-10-27 17:46 ` [PATCH 1/4] tests/qtest: Make netfilter tests accept padded ethernet packets Peter Maydell
2026-10-27 17:46 ` [PATCH 2/4] net: Set do_not_pad for net backends Peter Maydell
@ 2026-10-27 17:46 ` Peter Maydell
2026-10-27 17:46 ` [PATCH 4/4] net: Remove padding code from net backends Peter Maydell
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2026-10-27 17:46 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Fleytman, Akihiko Odaki, Jason Wang, Samuel Thibault,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
Daniel P. Berrangé, Zhang Chen, Li Zhijian
Now that we can rely on do_not_pad being correct for all
NetClientInfo structs, we can pad short packets in the
qemu_send_packet() and qemu_sendv_packet() family of functions.
If the callsite is already padding, then this will have no effect,
but callsites like the socket and dgram backends will now correctly
add padding. This fixes the bug where when two QEMU instances are
connected via one of those backends a short ARP packet transmitted by
one is not correctly padded by the other and gets dropped.
Note that if we pad a packet, our return value on success will
be the size of the padded packet, not the original. This is OK
because this function (like the NetQueueDeliverFunc function type
documented in include/net/queue.h and which we will eventually
end up calling and returning the return value of) returns
>0 - success
0 - queue packet for future redelivery
<0 - failure (discard packet)
and doesn't guarantee to return exactly the size of the packet
sent. None of the callers try to use the return value as an
exact size.
Cc: qemu-stable@nongu.org
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/2362
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/net/eth.h | 22 ++++++++++++++++++++++
net/eth.c | 18 ++++++++++++++++++
net/net.c | 22 ++++++++++++++++++++++
3 files changed, 62 insertions(+)
diff --git a/include/net/eth.h b/include/net/eth.h
index 46dc9ed5acd..042b2fc42db 100644
--- a/include/net/eth.h
+++ b/include/net/eth.h
@@ -437,4 +437,26 @@ eth_parse_ipv6_hdr(const struct iovec *pkt, int pkt_frags,
bool eth_pad_short_frame(uint8_t *padded_pkt, size_t *padded_buflen,
const void *pkt, size_t pkt_size);
+/**
+ * eth_pad_short_frame_iov - pad a short frame, iovec version
+ *
+ * This is equivalent to eth_pad_short_frame(), except that it works
+ * on a packet stored in a struct iovec.
+ *
+ * If the Ethernet frame size is shorter than 60 bytes, it will be padded to
+ * 60 bytes at the address @padded_pkt (and the caller will need to handle
+ * it as a not-in-an-iovec packet).
+ *
+ * @padded_pkt: buffer address to hold the padded frame
+ * @padded_buflen: pointer holding length of @padded_pkt. If the frame is
+ * padded, the length will be updated to the padded one.
+ * @iov: iovec holding the original Ethernet frame
+ * @iovcnt: number of elements in @iov
+ * @pkt_size: size of the original Ethernet frame (i.e. iov_size(iov, iovcnt))
+ * @return true if the frame is padded, otherwise false
+ */
+bool eth_pad_short_frame_iov(uint8_t *padded_pkt, size_t *padded_buflen,
+ const struct iovec *iov, int iovcnt,
+ size_t pkt_size);
+
#endif
diff --git a/net/eth.c b/net/eth.c
index 12ec316e240..14006222d68 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -536,3 +536,21 @@ bool eth_pad_short_frame(uint8_t *padded_pkt, size_t *padded_buflen,
return true;
}
+
+bool eth_pad_short_frame_iov(uint8_t *padded_pkt, size_t *padded_buflen,
+ const struct iovec *iov, int iovcnt,
+ size_t pkt_size)
+{
+ assert(padded_buflen && *padded_buflen >= ETH_ZLEN);
+
+ if (pkt_size >= ETH_ZLEN) {
+ return false;
+ }
+
+ /* pad to minimum Ethernet frame length */
+ iov_to_buf(iov, iovcnt, 0, padded_pkt, pkt_size);
+ memset(&padded_pkt[pkt_size], 0, ETH_ZLEN - pkt_size);
+ *padded_buflen = ETH_ZLEN;
+
+ return true;
+}
diff --git a/net/net.c b/net/net.c
index 1042a9d3a8e..408871d3c21 100644
--- a/net/net.c
+++ b/net/net.c
@@ -735,6 +735,8 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
{
NetQueue *queue;
int ret;
+ uint8_t min_pkt[ETH_ZLEN];
+ size_t min_pktsz = sizeof(min_pkt);
#ifdef DEBUG_NET
printf("qemu_send_packet_async:\n");
@@ -745,6 +747,13 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
return size;
}
+ if (net_peer_needs_padding(sender)) {
+ if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
+ buf = min_pkt;
+ size = min_pktsz;
+ }
+ }
+
/* Let filters handle the packet first */
ret = filter_receive(sender, NET_FILTER_DIRECTION_TX,
sender, flags, buf, size, sent_cb);
@@ -899,6 +908,19 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender,
return size;
}
+ if (net_peer_needs_padding(sender)) {
+ uint8_t min_pkt[ETH_ZLEN];
+ size_t min_pktsz = sizeof(min_pkt);
+
+ /*
+ * If we pad the packet, we get back a simple buffer, so handle
+ * it by sending it to the non-iov qemu_send_packet function
+ */
+ if (eth_pad_short_frame_iov(min_pkt, &min_pktsz, iov, iovcnt, size)) {
+ return qemu_send_packet_async(sender, min_pkt, min_pktsz, sent_cb);
+ }
+ }
+
/* Let filters handle the packet first */
ret = filter_receive_iov(sender, NET_FILTER_DIRECTION_TX, sender,
QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] net: Remove padding code from net backends
2026-10-27 17:46 [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
` (2 preceding siblings ...)
2026-10-27 17:46 ` [PATCH 3/4] net: Pad short packets in qemu_send_packet and qemu_sendv_packet Peter Maydell
@ 2026-10-27 17:46 ` Peter Maydell
2026-10-27 21:02 ` [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
2026-10-28 13:01 ` Peter Maydell
5 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2026-10-27 17:46 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Fleytman, Akihiko Odaki, Jason Wang, Samuel Thibault,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
Daniel P. Berrangé, Zhang Chen, Li Zhijian
We can remove the short-frame padding code from the net backends that
were previously doing it, because the qemu_send_packet and
qemu_sendv_packet calls they use now do the padding for them.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
net/slirp.c | 9 ---------
net/tap-win32.c | 15 ++-------------
net/tap.c | 9 ---------
net/vmnet-common.m | 11 -----------
4 files changed, 2 insertions(+), 42 deletions(-)
diff --git a/net/slirp.c b/net/slirp.c
index 451c0fd1ba4..eea12e79816 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -120,15 +120,6 @@ static ssize_t net_slirp_send_packet(const void *pkt, size_t pkt_len,
void *opaque)
{
SlirpState *s = opaque;
- uint8_t min_pkt[ETH_ZLEN];
- size_t min_pktsz = sizeof(min_pkt);
-
- if (net_peer_needs_padding(&s->nc)) {
- if (eth_pad_short_frame(min_pkt, &min_pktsz, pkt, pkt_len)) {
- pkt = min_pkt;
- pkt_len = min_pktsz;
- }
- }
return qemu_send_packet(&s->nc, pkt, pkt_len);
}
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 38baf90e0b3..2fccfdbaacf 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -682,25 +682,14 @@ static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
static void tap_win32_send(void *opaque)
{
TAPState *s = opaque;
- uint8_t *buf, *orig_buf;
+ uint8_t *buf;
int max_size = 4096;
int size;
- uint8_t min_pkt[ETH_ZLEN];
- size_t min_pktsz = sizeof(min_pkt);
size = tap_win32_read(s->handle, &buf, max_size);
if (size > 0) {
- orig_buf = buf;
-
- if (net_peer_needs_padding(&s->nc)) {
- if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
- buf = min_pkt;
- size = min_pktsz;
- }
- }
-
qemu_send_packet(&s->nc, buf, size);
- tap_win32_free_buffer(s->handle, orig_buf);
+ tap_win32_free_buffer(s->handle, buf);
}
}
diff --git a/net/tap.c b/net/tap.c
index ada69a21021..786c31f5adf 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -261,8 +261,6 @@ static void tap_send(void *opaque)
while (true) {
uint8_t *buf = s->buf;
- uint8_t min_pkt[ETH_ZLEN];
- size_t min_pktsz = sizeof(min_pkt);
size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
if (size <= 0) {
@@ -279,13 +277,6 @@ static void tap_send(void *opaque)
size -= s->host_vnet_hdr_len;
}
- if (net_peer_needs_padding(&s->nc)) {
- if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
- buf = min_pkt;
- size = min_pktsz;
- }
- }
-
size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed);
if (size == 0) {
tap_read_poll(s, false);
diff --git a/net/vmnet-common.m b/net/vmnet-common.m
index ab33ce2b0c2..4dfc8abbc15 100644
--- a/net/vmnet-common.m
+++ b/net/vmnet-common.m
@@ -150,23 +150,12 @@ static void vmnet_write_packets_to_qemu(VmnetState *s)
{
uint8_t *pkt;
size_t pktsz;
- uint8_t min_pkt[ETH_ZLEN];
- size_t min_pktsz;
ssize_t size;
while (s->packets_send_current_pos < s->packets_send_end_pos) {
pkt = s->iov_buf[s->packets_send_current_pos].iov_base;
pktsz = s->packets_buf[s->packets_send_current_pos].vm_pkt_size;
- if (net_peer_needs_padding(&s->nc)) {
- min_pktsz = sizeof(min_pkt);
-
- if (eth_pad_short_frame(min_pkt, &min_pktsz, pkt, pktsz)) {
- pkt = min_pkt;
- pktsz = min_pktsz;
- }
- }
-
size = qemu_send_packet_async(&s->nc, pkt, pktsz,
vmnet_send_completed);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4] net: Consistently pad short packets for all backends
2026-10-27 17:46 [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
` (3 preceding siblings ...)
2026-10-27 17:46 ` [PATCH 4/4] net: Remove padding code from net backends Peter Maydell
@ 2026-10-27 21:02 ` Peter Maydell
2026-10-28 13:01 ` Peter Maydell
5 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2026-10-27 21:02 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Fleytman, Akihiko Odaki, Jason Wang, Samuel Thibault,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
Daniel P. Berrangé, Zhang Chen, Li Zhijian, Bin Meng
Oops, I meant to cc Bin on this series as it's the result of
a previous thread on the topic, but forgot...
https://lore.kernel.org/qemu-devel/CAFEAcA_UhmCxJc16CHE=4ZR1+PA0=4-29=fEe+d+iUmhLTzpuQ@mail.gmail.com/
-- PMM
On Tue, 27 Oct 2026 at 17:46, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> The net core code design is that by default packets are padded out to
> the ethernet frame minimum before being handed to a network device
> model, unless that device explicitly opted in by setting do_not_pad.
> This avoids a whole class of bugs where network device receive code
> has to be very careful about handling short packets.
>
> However, at the moment we do this check manually in the network
> backend code before it calls qemu_send_packet() or
> qemu_send_packet_async(), and we forgot to do it in all backends. So
> you get the padding for the slirp, tap and vmnet backends, but not
> for the "minor" backends like 'passt', 'socket' and 'dgram', or if
> you configure two network devices connected by an emulated hub.
>
> This series fixes this by moving the padding code to
> qemu_send_packet()/qemu_sendv_packet(), so that it always happens
> regardless of the backend.
>
> The main bug this is fixing is
> https://gitlab.com/qemu-project/qemu/-/work_items/2362
> but it's been re-reported multiple times for various combinations
> of network devices and backends.
>
> The whole series is cc stable because without the padding you can
> provoke various bugs in different network device models.
>
> thanks
> -- PMM
>
> Peter Maydell (4):
> tests/qtest: Make netfilter tests accept padded ethernet packets
> net: Set do_not_pad for net backends
> net: Pad short packets in qemu_send_packet and qemu_sendv_packet
> net: Remove padding code from net backends
>
> include/net/eth.h | 22 +++++++++++++++++++
> include/net/net.h | 3 ++-
> net/eth.c | 18 ++++++++++++++++
> net/net.c | 32 ++++++++++++++++++++++++----
> net/slirp.c | 9 --------
> net/tap-win32.c | 15 ++-----------
> net/tap.c | 11 +---------
> tests/qtest/test-filter-buffer.c | 4 +++-
> tests/qtest/test-filter-mirror.c | 4 +++-
> tests/qtest/test-filter-redirector.c | 4 +++-
> net/vmnet-common.m | 11 ----------
> 11 files changed, 82 insertions(+), 51 deletions(-)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4] net: Consistently pad short packets for all backends
2026-10-27 17:46 [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
` (4 preceding siblings ...)
2026-10-27 21:02 ` [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
@ 2026-10-28 13:01 ` Peter Maydell
5 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2026-10-28 13:01 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Fleytman, Akihiko Odaki, Jason Wang, Samuel Thibault,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
Daniel P. Berrangé, Zhang Chen, Li Zhijian, Bin Meng
On Tue, 27 Oct 2026 at 17:46, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> The net core code design is that by default packets are padded out to
> the ethernet frame minimum before being handed to a network device
> model, unless that device explicitly opted in by setting do_not_pad.
> This avoids a whole class of bugs where network device receive code
> has to be very careful about handling short packets.
>
> However, at the moment we do this check manually in the network
> backend code before it calls qemu_send_packet() or
> qemu_send_packet_async(), and we forgot to do it in all backends. So
> you get the padding for the slirp, tap and vmnet backends, but not
> for the "minor" backends like 'passt', 'socket' and 'dgram', or if
> you configure two network devices connected by an emulated hub.
>
> This series fixes this by moving the padding code to
> qemu_send_packet()/qemu_sendv_packet(), so that it always happens
> regardless of the backend.
>
> The main bug this is fixing is
> https://gitlab.com/qemu-project/qemu/-/work_items/2362
> but it's been re-reported multiple times for various combinations
> of network devices and backends.
>
> The whole series is cc stable because without the padding you can
> provoke various bugs in different network device models.
This has now been assigned CVE-2026-118490.
-- PMM
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] tests/qtest: Make netfilter tests accept padded ethernet packets
2026-10-27 17:46 ` [PATCH 1/4] tests/qtest: Make netfilter tests accept padded ethernet packets Peter Maydell
@ 2026-10-28 13:29 ` Fabiano Rosas
0 siblings, 0 replies; 8+ messages in thread
From: Fabiano Rosas @ 2026-10-28 13:29 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Dmitry Fleytman, Akihiko Odaki, Jason Wang, Samuel Thibault,
Laurent Vivier, Paolo Bonzini, Daniel P. Berrangé,
Zhang Chen, Li Zhijian
Peter Maydell <peter.maydell@linaro.org> writes:
> Currently the various netfilter tests assume and assert that the data
> they get from the filter is an exact match for the data that they
> send in to it via the net socket backend. This happens to be the
> case currently because the net socket backend fails to pad frames to
> the ethernet minimum when the device expects that (unlike e.g. the
> tap backend). When we fix the socket backend to honour the device's
> request for padding, the netfilter will see padded packets for
> devices that require them (which is most of them), and not for those
> that don't (notably virtio-net).
>
> This seems best considered as a test error: if you're using netfilter
> to look at what a particular network device is receiving, you want to
> actually see what it is receiving. And most real-world users of
> filtering will be doing it with the backends like TAP that were
> already doing pad-before-filter; it's only the oddball backends like
> 'socket' that forgot to pad.
>
> Make the test cases accept as valid both padded and unpadded frames.
>
> Cc: qemu-stable@nongnu.org
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> tests/qtest/test-filter-buffer.c | 4 +++-
> tests/qtest/test-filter-mirror.c | 4 +++-
> tests/qtest/test-filter-redirector.c | 4 +++-
> 3 files changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/tests/qtest/test-filter-buffer.c b/tests/qtest/test-filter-buffer.c
> index 441cbb975ca..418caccf00a 100644
> --- a/tests/qtest/test-filter-buffer.c
> +++ b/tests/qtest/test-filter-buffer.c
> @@ -11,6 +11,7 @@
> #include "qobject/qdict.h"
> #include "qemu/iov.h"
> #include "qemu/sockets.h"
> +#include "net/eth.h"
>
> /*
> * Test that changing interval at runtime affects packet release timing.
> @@ -148,7 +149,8 @@ static void test_change_interval_timer(void)
> ret = recv(recv_sock, &len, sizeof(len), 0);
> g_assert_cmpint(ret, ==, sizeof(len));
> len = ntohl(len);
> - g_assert_cmpint(len, ==, sizeof(send_buf));
> + /* The snooped network device might or might not have asked for padding */
> + g_assert(len == sizeof(send_buf) || len == MAX(sizeof(send_buf), ETH_ZLEN));
>
> ret = recv(recv_sock, recv_buf, len, 0);
> g_assert_cmpint(ret, ==, len);
> diff --git a/tests/qtest/test-filter-mirror.c b/tests/qtest/test-filter-mirror.c
> index 723d2c2f291..9972712cb49 100644
> --- a/tests/qtest/test-filter-mirror.c
> +++ b/tests/qtest/test-filter-mirror.c
> @@ -15,6 +15,7 @@
> #include "qemu/sockets.h"
> #include "qemu/error-report.h"
> #include "qemu/main-loop.h"
> +#include "net/eth.h"
>
> static void test_mirror(void)
> {
> @@ -58,7 +59,8 @@ static void test_mirror(void)
> g_assert_cmpint(ret, ==, sizeof(len));
> len = ntohl(len);
>
> - g_assert_cmpint(len, ==, sizeof(send_buf));
> + /* The snooped network device might or might not have asked for padding */
> + g_assert(len == sizeof(send_buf) || len == MAX(sizeof(send_buf), ETH_ZLEN));
> recv_buf = g_malloc(len);
> ret = recv(recv_sock[0], recv_buf, len, 0);
> g_assert_cmpint(ret, ==, len);
> diff --git a/tests/qtest/test-filter-redirector.c b/tests/qtest/test-filter-redirector.c
> index 5540c232c0b..a4f9b73c72a 100644
> --- a/tests/qtest/test-filter-redirector.c
> +++ b/tests/qtest/test-filter-redirector.c
> @@ -57,6 +57,7 @@
> #include "qemu/sockets.h"
> #include "qemu/error-report.h"
> #include "qemu/main-loop.h"
> +#include "net/eth.h"
>
> static void test_redirector_tx(void)
> {
> @@ -115,7 +116,8 @@ static void test_redirector_tx(void)
> g_assert_cmpint(ret, ==, sizeof(len));
> len = ntohl(len);
>
> - g_assert_cmpint(len, ==, sizeof(send_buf));
> + /* The snooped network device might or might not have asked for padding */
> + g_assert(len == sizeof(send_buf) || len == MAX(sizeof(send_buf), ETH_ZLEN));
> recv_buf = g_malloc(len);
> ret = recv(recv_sock, recv_buf, len, 0);
> g_assert_cmpint(ret, ==, len);
Reviewed-by: Fabiano Rosas <farosas@suse.de>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-28 13:30 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-27 17:46 [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
2026-10-27 17:46 ` [PATCH 1/4] tests/qtest: Make netfilter tests accept padded ethernet packets Peter Maydell
2026-10-28 13:29 ` Fabiano Rosas
2026-10-27 17:46 ` [PATCH 2/4] net: Set do_not_pad for net backends Peter Maydell
2026-10-27 17:46 ` [PATCH 3/4] net: Pad short packets in qemu_send_packet and qemu_sendv_packet Peter Maydell
2026-10-27 17:46 ` [PATCH 4/4] net: Remove padding code from net backends Peter Maydell
2026-10-27 21:02 ` [PATCH 0/4] net: Consistently pad short packets for all backends Peter Maydell
2026-10-28 13:01 ` Peter Maydell
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.