From nobody Sun Feb 8 20:28:24 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=philmd@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=philmd@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1625474417; cv=none; d=zohomail.com; s=zohoarc; b=idhTSPjA0vS4SxRez20cPpkuancHthlgTiez7RI+sjqmeYcbbiZlKGhTjJs+1suDp9ccRlO11T4xYS4SmVlmIXgHpmurEGAAM0dbLPkjz5yOAc/3Qt5u1LhJjY8WaCacmE91MynDYsetj3dev6/omhM8angaZjsp00ljzFxHjwI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625474417; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:MIME-Version:Message-ID:Subject:To; bh=739BGhT/S22dZHAbNyIAUJ6Qz+I6opGAjS8tM4gSWXw=; b=UyjlYqKo45JJltwf0d2ugXlUnRnQj9QT1BE4nEWnKmykAAYybebsqf0P5LsGqC2f+MF60qP5DvnxmSzH8jVXIJL7t+IdtdwRCY7sDFs6SsLt4k6xanAUZjQWxd1/LUxbWnURsHL91qsVFxwAuISyWGN61M3gaR9EZXzUqLMCO7A= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=philmd@redhat.com; dmarc=pass header.from= (p=none dis=none) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1625474417577211.89665438601628; Mon, 5 Jul 2021 01:40:17 -0700 (PDT) Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-210-iKvMH93FPdGYrGydrCDDNw-1; Mon, 05 Jul 2021 04:40:14 -0400 Received: by mail-wm1-f70.google.com with SMTP id p6-20020a05600c3586b029020b46124c2eso350224wmq.1 for ; Mon, 05 Jul 2021 01:40:14 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.redhat.com (93.red-83-35-24.dynamicip.rima-tde.net. [83.35.24.93]) by smtp.gmail.com with ESMTPSA id j1sm810146wms.7.2021.07.05.01.40.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Jul 2021 01:40:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1625474416; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=739BGhT/S22dZHAbNyIAUJ6Qz+I6opGAjS8tM4gSWXw=; b=hdYHzQLwM+1FkVcM+RtghIxjxPNhApdiRwoqu2JBCv9L9h/vxquqbWw/RiWx2crzfe0bIx IQhwxwkuqZJ38CaKmarXGCvn7AZz/c88Bbpy9MEhnNZGq8/RRIa0qOc4aIOqKnAJ5fHO2R VWAn8/v0jBVAdvTiIGVlaId8UlKPL20= X-MC-Unique: iKvMH93FPdGYrGydrCDDNw-1 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=739BGhT/S22dZHAbNyIAUJ6Qz+I6opGAjS8tM4gSWXw=; b=SIJNnzuwhEOOALKXQMw+XzAQumvjf6aZ6BIeAOx2EYV01SBOuEkihzLpMPoe5UPsR0 jcrcjYJtbmPxPZ1775bGVJ5VdvU74YCZFn5VsEzbRXO4eiFbbK9/HjeSJXzcWGMuLISQ zgVED0y40J4SdhGXCqDWwYdTLWOIaCvKjl9tYKVb6F7nE3ej1IxgxZIIWgWPF5iVloUx UShE8mdYuMwNlYPeoDRD5fXVABkM4l6HtusP3TiCNDlYysn8GuwMU3ZslUZfwxGoxKmy PqDCIIlAdsODcXB5ciery0GAZKg35Bd9RJ0Sm4iO5WuiOr1ie1jdaz5Im7ZWp9TJKg0l sfQQ== X-Gm-Message-State: AOAM530y639j1cM2r3vl43QkveaxSnpJ+uPTQ37s93R8z28FjEhsuTGF CnHaBLUiez/I6XRHYzi5nCtKKQK4J9MkvyHITJqXKDL0SHeswBiR/1Fk40dXop4tb2nOP0qc+uI 3tCt/36IDNYUs9A== X-Received: by 2002:adf:fe12:: with SMTP id n18mr14059276wrr.219.1625474413126; Mon, 05 Jul 2021 01:40:13 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyFClVr3gER1V0BeARoQi/uE/lHsbCJd2hQb+7ZrTn34QiHIX4dp+CJqyhb7kAye2x/Jx9WyQ== X-Received: by 2002:adf:fe12:: with SMTP id n18mr14059245wrr.219.1625474412830; Mon, 05 Jul 2021 01:40:12 -0700 (PDT) From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Cc: Mauro Matteo Cascella , Andrew Melnychenko , Alexander Bulekov , Jason Wang , Li Qiang , Dmitry Fleytman , Prasad J Pandit , Thomas Huth , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , qemu-stable@nongnu.org Subject: [PATCH] hw/net: Discard overly fragmented packets Date: Mon, 5 Jul 2021 10:40:11 +0200 Message-Id: <20210705084011.814175-1-philmd@redhat.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=philmd@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1625474424867100001 Our infrastructure can handle fragmented packets up to NET_MAX_FRAG_SG_LIST (64) pieces. This hard limit has been proven enough in production for years. If it is reached, it is likely an evil crafted packet. Discard it. Include the qtest reproducer provided by Alexander Bulekov: $ make check-qtest-i386 ... Running test qtest-i386/fuzz-vmxnet3-test qemu-system-i386: net/eth.c:334: void eth_setup_ip4_fragmentation(const v= oid *, size_t, void *, size_t, size_t, size_t, _Bool): Assertion `frag_offset % IP_FRAG_UNIT_SIZE =3D=3D 0' failed. Cc: qemu-stable@nongnu.org Reported-by: OSS-Fuzz (Issue 35799) Resolves: https://gitlab.com/qemu-project/qemu/-/issues/460 Signed-off-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Thomas Huth --- hw/net/net_tx_pkt.c | 8 ++ tests/qtest/fuzz-vmxnet3-test.c | 195 ++++++++++++++++++++++++++++++++ MAINTAINERS | 1 + tests/qtest/meson.build | 1 + 4 files changed, 205 insertions(+) create mode 100644 tests/qtest/fuzz-vmxnet3-test.c diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c index 1f9aa59eca2..77e9729a7ba 100644 --- a/hw/net/net_tx_pkt.c +++ b/hw/net/net_tx_pkt.c @@ -590,6 +590,14 @@ static bool net_tx_pkt_do_sw_fragmentation(struct NetT= xPkt *pkt, fragment_len =3D net_tx_pkt_fetch_fragment(pkt, &src_idx, &src_off= set, fragment, &dst_idx); =20 + if (dst_idx =3D=3D NET_MAX_FRAG_SG_LIST && fragment_len > 0) { + /* + * The packet is too fragmented for our infrastructure + * (not enough iovec), don't even try to send. + */ + return false; + } + more_frags =3D (fragment_offset + fragment_len < pkt->payload_len); =20 eth_setup_ip4_fragmentation(l2_iov_base, l2_iov_len, l3_iov_base, diff --git a/tests/qtest/fuzz-vmxnet3-test.c b/tests/qtest/fuzz-vmxnet3-tes= t.c new file mode 100644 index 00000000000..d69009bf5ce --- /dev/null +++ b/tests/qtest/fuzz-vmxnet3-test.c @@ -0,0 +1,195 @@ +/* + * QTest testcase for vmxnet3 device generated by fuzzer + * + * Copyright Red Hat + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include "libqos/libqtest.h" + +/* + * https://gitlab.com/qemu-project/qemu/-/issues/460 + */ +static void test_oss_35799_eth_setup_ip4_fragmentation(void) +{ + QTestState *s; + + s =3D qtest_init("-machine q35 -m 32M -display none -nodefaults " + "-device vmxnet3,netdev=3Dnet0 -netdev user,id=3Dnet0"); + qtest_outl(s, 0xcf8, 0x80000814); + qtest_outl(s, 0xcfc, 0xe0000000); + qtest_outl(s, 0xcf8, 0x80000804); + qtest_outw(s, 0xcfc, 0x06); + qtest_outl(s, 0xcf8, 0x80000812); + qtest_outl(s, 0xcfc, 0x2000); + qtest_outl(s, 0xcf8, 0x80000815); + qtest_outb(s, 0xcfc, 0x40); + qtest_bufwrite(s, 0x0, "\xe1", 0x1); + qtest_bufwrite(s, 0x1, "\xfe", 0x1); + qtest_bufwrite(s, 0x2, "\xbe", 0x1); + qtest_bufwrite(s, 0x3, "\xba", 0x1); + qtest_bufwrite(s, 0x28, "\xff", 0x1); + qtest_bufwrite(s, 0x29, "\xff", 0x1); + qtest_bufwrite(s, 0x2a, "\xff", 0x1); + qtest_bufwrite(s, 0x2b, "\xff", 0x1); + qtest_bufwrite(s, 0x2c, "\xff", 0x1); + qtest_bufwrite(s, 0x2d, "\xff", 0x1); + qtest_bufwrite(s, 0x2e, "\xff", 0x1); + qtest_bufwrite(s, 0x2f, "\xff", 0x1); + qtest_bufwrite(s, 0x37, "\x40", 0x1); + qtest_bufwrite(s, 0x3e, "\x01", 0x1); + qtest_bufwrite(s, 0xe0004020, "\x00\x00\xfe\xca", 0x4); + qtest_bufwrite(s, 0x9, "\x40", 0x1); + qtest_bufwrite(s, 0xd, "\x10", 0x1); + qtest_bufwrite(s, 0x12, "\x10", 0x1); + qtest_bufwrite(s, 0x19, "\x40", 0x1); + qtest_bufwrite(s, 0x1b, "\x21", 0x1); + qtest_bufwrite(s, 0x1d, "\x0c", 0x1); + qtest_bufwrite(s, 0x2d, "\x00", 0x1); + qtest_bufwrite(s, 0x10000c, "\x08", 0x1); + qtest_bufwrite(s, 0x10000e, "\x45", 0x1); + qtest_bufwrite(s, 0x100017, "\x11", 0x1); + qtest_bufwrite(s, 0x20000600, "\x00", 0x1); + qtest_bufwrite(s, 0x38, "\x01", 0x1); + qtest_bufwrite(s, 0x39, "\x40", 0x1); + qtest_bufwrite(s, 0x48, "\x01", 0x1); + qtest_bufwrite(s, 0x49, "\x40", 0x1); + qtest_bufwrite(s, 0x58, "\x01", 0x1); + qtest_bufwrite(s, 0x59, "\x40", 0x1); + qtest_bufwrite(s, 0x68, "\x01", 0x1); + qtest_bufwrite(s, 0x69, "\x40", 0x1); + qtest_bufwrite(s, 0x78, "\x01", 0x1); + qtest_bufwrite(s, 0x79, "\x40", 0x1); + qtest_bufwrite(s, 0x88, "\x01", 0x1); + qtest_bufwrite(s, 0x89, "\x40", 0x1); + qtest_bufwrite(s, 0x98, "\x01", 0x1); + qtest_bufwrite(s, 0x99, "\x40", 0x1); + qtest_bufwrite(s, 0xa8, "\x01", 0x1); + qtest_bufwrite(s, 0xa9, "\x40", 0x1); + qtest_bufwrite(s, 0xb8, "\x01", 0x1); + qtest_bufwrite(s, 0xb9, "\x40", 0x1); + qtest_bufwrite(s, 0xc8, "\x01", 0x1); + qtest_bufwrite(s, 0xc9, "\x40", 0x1); + qtest_bufwrite(s, 0xd8, "\x01", 0x1); + qtest_bufwrite(s, 0xd9, "\x40", 0x1); + qtest_bufwrite(s, 0xe8, "\x01", 0x1); + qtest_bufwrite(s, 0xe9, "\x40", 0x1); + qtest_bufwrite(s, 0xf8, "\x01", 0x1); + qtest_bufwrite(s, 0xf9, "\x40", 0x1); + qtest_bufwrite(s, 0x108, "\x01", 0x1); + qtest_bufwrite(s, 0x109, "\x40", 0x1); + qtest_bufwrite(s, 0x118, "\x01", 0x1); + qtest_bufwrite(s, 0x119, "\x40", 0x1); + qtest_bufwrite(s, 0x128, "\x01", 0x1); + qtest_bufwrite(s, 0x129, "\x40", 0x1); + qtest_bufwrite(s, 0x138, "\x01", 0x1); + qtest_bufwrite(s, 0x139, "\x40", 0x1); + qtest_bufwrite(s, 0x148, "\x01", 0x1); + qtest_bufwrite(s, 0x149, "\x40", 0x1); + qtest_bufwrite(s, 0x158, "\x01", 0x1); + qtest_bufwrite(s, 0x159, "\x40", 0x1); + qtest_bufwrite(s, 0x168, "\x01", 0x1); + qtest_bufwrite(s, 0x169, "\x40", 0x1); + qtest_bufwrite(s, 0x178, "\x01", 0x1); + qtest_bufwrite(s, 0x179, "\x40", 0x1); + qtest_bufwrite(s, 0x188, "\x01", 0x1); + qtest_bufwrite(s, 0x189, "\x40", 0x1); + qtest_bufwrite(s, 0x198, "\x01", 0x1); + qtest_bufwrite(s, 0x199, "\x40", 0x1); + qtest_bufwrite(s, 0x1a8, "\x01", 0x1); + qtest_bufwrite(s, 0x1a9, "\x40", 0x1); + qtest_bufwrite(s, 0x1b8, "\x01", 0x1); + qtest_bufwrite(s, 0x1b9, "\x40", 0x1); + qtest_bufwrite(s, 0x1c8, "\x01", 0x1); + qtest_bufwrite(s, 0x1c9, "\x40", 0x1); + qtest_bufwrite(s, 0x1d8, "\x01", 0x1); + qtest_bufwrite(s, 0x1d9, "\x40", 0x1); + qtest_bufwrite(s, 0x1e8, "\x01", 0x1); + qtest_bufwrite(s, 0x1e9, "\x40", 0x1); + qtest_bufwrite(s, 0x1f8, "\x01", 0x1); + qtest_bufwrite(s, 0x1f9, "\x40", 0x1); + qtest_bufwrite(s, 0x208, "\x01", 0x1); + qtest_bufwrite(s, 0x209, "\x40", 0x1); + qtest_bufwrite(s, 0x218, "\x01", 0x1); + qtest_bufwrite(s, 0x219, "\x40", 0x1); + qtest_bufwrite(s, 0x228, "\x01", 0x1); + qtest_bufwrite(s, 0x229, "\x40", 0x1); + qtest_bufwrite(s, 0x238, "\x01", 0x1); + qtest_bufwrite(s, 0x239, "\x40", 0x1); + qtest_bufwrite(s, 0x248, "\x01", 0x1); + qtest_bufwrite(s, 0x249, "\x40", 0x1); + qtest_bufwrite(s, 0x258, "\x01", 0x1); + qtest_bufwrite(s, 0x259, "\x40", 0x1); + qtest_bufwrite(s, 0x268, "\x01", 0x1); + qtest_bufwrite(s, 0x269, "\x40", 0x1); + qtest_bufwrite(s, 0x278, "\x01", 0x1); + qtest_bufwrite(s, 0x279, "\x40", 0x1); + qtest_bufwrite(s, 0x288, "\x01", 0x1); + qtest_bufwrite(s, 0x289, "\x40", 0x1); + qtest_bufwrite(s, 0x298, "\x01", 0x1); + qtest_bufwrite(s, 0x299, "\x40", 0x1); + qtest_bufwrite(s, 0x2a8, "\x01", 0x1); + qtest_bufwrite(s, 0x2a9, "\x40", 0x1); + qtest_bufwrite(s, 0x2b8, "\x01", 0x1); + qtest_bufwrite(s, 0x2b9, "\x40", 0x1); + qtest_bufwrite(s, 0x2c8, "\x01", 0x1); + qtest_bufwrite(s, 0x2c9, "\x40", 0x1); + qtest_bufwrite(s, 0x2d8, "\x01", 0x1); + qtest_bufwrite(s, 0x2d9, "\x40", 0x1); + qtest_bufwrite(s, 0x2e8, "\x01", 0x1); + qtest_bufwrite(s, 0x2e9, "\x40", 0x1); + qtest_bufwrite(s, 0x2f8, "\x01", 0x1); + qtest_bufwrite(s, 0x2f9, "\x40", 0x1); + qtest_bufwrite(s, 0x308, "\x01", 0x1); + qtest_bufwrite(s, 0x309, "\x40", 0x1); + qtest_bufwrite(s, 0x318, "\x01", 0x1); + qtest_bufwrite(s, 0x319, "\x40", 0x1); + qtest_bufwrite(s, 0x328, "\x01", 0x1); + qtest_bufwrite(s, 0x329, "\x40", 0x1); + qtest_bufwrite(s, 0x338, "\x01", 0x1); + qtest_bufwrite(s, 0x339, "\x40", 0x1); + qtest_bufwrite(s, 0x348, "\x01", 0x1); + qtest_bufwrite(s, 0x349, "\x40", 0x1); + qtest_bufwrite(s, 0x358, "\x01", 0x1); + qtest_bufwrite(s, 0x359, "\x40", 0x1); + qtest_bufwrite(s, 0x368, "\x01", 0x1); + qtest_bufwrite(s, 0x369, "\x40", 0x1); + qtest_bufwrite(s, 0x378, "\x01", 0x1); + qtest_bufwrite(s, 0x379, "\x40", 0x1); + qtest_bufwrite(s, 0x388, "\x01", 0x1); + qtest_bufwrite(s, 0x389, "\x40", 0x1); + qtest_bufwrite(s, 0x398, "\x01", 0x1); + qtest_bufwrite(s, 0x399, "\x40", 0x1); + qtest_bufwrite(s, 0x3a8, "\x01", 0x1); + qtest_bufwrite(s, 0x3a9, "\x40", 0x1); + qtest_bufwrite(s, 0x3b8, "\x01", 0x1); + qtest_bufwrite(s, 0x3b9, "\x40", 0x1); + qtest_bufwrite(s, 0x3c8, "\x01", 0x1); + qtest_bufwrite(s, 0x3c9, "\x40", 0x1); + qtest_bufwrite(s, 0x3d8, "\x01", 0x1); + qtest_bufwrite(s, 0x3d9, "\x40", 0x1); + qtest_bufwrite(s, 0x3e8, "\x01", 0x1); + qtest_bufwrite(s, 0x3e9, "\x40", 0x1); + qtest_bufwrite(s, 0x3f8, "\x01", 0x1); + qtest_bufwrite(s, 0x3f9, "\x40", 0x1); + qtest_bufwrite(s, 0xd, "\x10", 0x1); + qtest_bufwrite(s, 0x20000600, "\x00", 0x1); + qtest_quit(s); +} + +int main(int argc, char **argv) +{ + const char *arch =3D qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + if (strcmp(arch, "i386") =3D=3D 0 || strcmp(arch, "x86_64") =3D=3D 0) { + qtest_add_func("fuzz/test_oss_35799_eth_setup_ip4_fragmentation", + test_oss_35799_eth_setup_ip4_fragmentation); + } + + return g_test_run(); +} diff --git a/MAINTAINERS b/MAINTAINERS index cb8f3ea2c2e..43e5050ad96 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2001,6 +2001,7 @@ S: Maintained F: hw/net/vmxnet* F: hw/scsi/vmw_pvscsi* F: tests/qtest/vmxnet3-test.c +F: tests/qtest/fuzz-vmxnet3-test.c =20 Rocker M: Jiri Pirko diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index b03e8541700..42add92e9d4 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -66,6 +66,7 @@ (config_all_devices.has_key('CONFIG_TPM_TIS_ISA') ? ['tpm-tis-swtpm-test= '] : []) + \ (config_all_devices.has_key('CONFIG_RTL8139_PCI') ? ['rtl8139-test'] : [= ]) + \ (config_all_devices.has_key('CONFIG_E1000E_PCI_EXPRESS') ? ['fuzz-e1000e= -test'] : []) + \ + (config_all_devices.has_key('CONFIG_VMXNET3_PCI') ? ['fuzz-vmxnet3-test'= ] : []) + \ (config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) = + \ qtests_pci + = \ ['fdc-test', --=20 2.31.1