All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mauro Matteo Cascella <mcascell@redhat.com>
To: "Philippe Mathieu-Daudé" <philmd@redhat.com>
Cc: Andrew Melnychenko <andrew@daynix.com>,
	Dmitry Fleytman <dmitry.fleytman@gmail.com>,
	Jason Wang <jasowang@redhat.com>, Li Qiang <liq3ea@gmail.com>,
	QEMU Developers <qemu-devel@nongnu.org>,
	Prasad J Pandit <ppandit@redhat.com>,
	Alexander Bulekov <alxndr@bu.edu>, Thomas Huth <thuth@redhat.com>,
	qemu-stable@nongnu.org
Subject: Re: [PATCH] hw/net: Discard overly fragmented packets
Date: Tue, 6 Jul 2021 11:00:12 +0200	[thread overview]
Message-ID: <CAA8xKjXwrbw-xo+YG8KaU8+Jg0zV4+GXW+hNjBfLDNwN7KG-ZA@mail.gmail.com> (raw)
In-Reply-To: <20210705084011.814175-1-philmd@redhat.com>

Hello Philippe,

I think you don't need root privileges to craft such a highly
fragmented packet from within the guest (tools like hping3 or nmap
come to mind). Right? If so, we may consider allocating a CVE for this
bug. If not, this is not CVE worthy - root does not need an assertion
failure to cause damage to the system.

On Mon, Jul 5, 2021 at 10:40 AM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> 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 void *, size_t, void *, size_t, size_t, size_t, _Bool):
>   Assertion `frag_offset % IP_FRAG_UNIT_SIZE == 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é <philmd@redhat.com>
> ---
>  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 NetTxPkt *pkt,
>          fragment_len = net_tx_pkt_fetch_fragment(pkt, &src_idx, &src_offset,
>              fragment, &dst_idx);
>
> +        if (dst_idx == 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 = (fragment_offset + fragment_len < pkt->payload_len);
>
>          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-test.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 = qtest_init("-machine q35 -m 32M -display none -nodefaults "
> +                   "-device vmxnet3,netdev=net0 -netdev user,id=net0");
> +    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 = qtest_get_arch();
> +
> +    g_test_init(&argc, &argv, NULL);
> +
> +    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 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
>
>  Rocker
>  M: Jiri Pirko <jiri@resnulli.us>
> 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',
> --
> 2.31.1
>


-- 
Mauro Matteo Cascella
Red Hat Product Security
PGP-Key ID: BB3410B0



  reply	other threads:[~2021-07-06  9:02 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-05  8:40 [PATCH] hw/net: Discard overly fragmented packets Philippe Mathieu-Daudé
2021-07-06  9:00 ` Mauro Matteo Cascella [this message]
2021-07-06  9:09   ` Philippe Mathieu-Daudé
2021-08-03  9:33 ` Thomas Huth
2021-08-03  9:51   ` Philippe Mathieu-Daudé
2021-08-04  1:43     ` Jason Wang
2021-08-11  4:08       ` Jason Wang
2022-08-05 14:51         ` Thomas Huth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAA8xKjXwrbw-xo+YG8KaU8+Jg0zV4+GXW+hNjBfLDNwN7KG-ZA@mail.gmail.com \
    --to=mcascell@redhat.com \
    --cc=alxndr@bu.edu \
    --cc=andrew@daynix.com \
    --cc=dmitry.fleytman@gmail.com \
    --cc=jasowang@redhat.com \
    --cc=liq3ea@gmail.com \
    --cc=philmd@redhat.com \
    --cc=ppandit@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-stable@nongnu.org \
    --cc=thuth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.