|
|
7711c0 |
From 4898198378a84fc6abd34adf5d0e297f4206b006 Mon Sep 17 00:00:00 2001
|
|
|
7711c0 |
From: Xiao Wang <jasowang@redhat.com>
|
|
|
7711c0 |
Date: Fri, 17 May 2019 07:29:37 +0200
|
|
|
7711c0 |
Subject: [PATCH 3/9] net: drop too large packet early
|
|
|
7711c0 |
|
|
|
7711c0 |
RH-Author: Xiao Wang <jasowang@redhat.com>
|
|
|
7711c0 |
Message-id: <1558078177-372-4-git-send-email-jasowang@redhat.com>
|
|
|
7711c0 |
Patchwork-id: 88015
|
|
|
7711c0 |
O-Subject: [RHEL7.7 qemu-kvm-rhev PATCH 3/3] net: drop too large packet early
|
|
|
7711c0 |
Bugzilla: 1636780
|
|
|
7711c0 |
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Maxime Coquelin <maxime.coquelin@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
Bugzilla: 1636779
|
|
|
7711c0 |
|
|
|
7711c0 |
We try to detect and drop too large packet (>INT_MAX) in 1592a9947036
|
|
|
7711c0 |
("net: ignore packet size greater than INT_MAX") during packet
|
|
|
7711c0 |
delivering. Unfortunately, this is not sufficient as we may hit
|
|
|
7711c0 |
another integer overflow when trying to queue such large packet in
|
|
|
7711c0 |
qemu_net_queue_append_iov():
|
|
|
7711c0 |
|
|
|
7711c0 |
- size of the allocation may overflow on 32bit
|
|
|
7711c0 |
- packet->size is integer which may overflow even on 64bit
|
|
|
7711c0 |
|
|
|
7711c0 |
Fixing this by moving the check to qemu_sendv_packet_async() which is
|
|
|
7711c0 |
the entrance of all networking codes and reduce the limit to
|
|
|
7711c0 |
NET_BUFSIZE to be more conservative. This works since:
|
|
|
7711c0 |
|
|
|
7711c0 |
- For the callers that call qemu_sendv_packet_async() directly, they
|
|
|
7711c0 |
only care about if zero is returned to determine whether to prevent
|
|
|
7711c0 |
the source from producing more packets. A callback will be triggered
|
|
|
7711c0 |
if peer can accept more then source could be enabled. This is
|
|
|
7711c0 |
usually used by high speed networking implementation like virtio-net
|
|
|
7711c0 |
or netmap.
|
|
|
7711c0 |
- For the callers that call qemu_sendv_packet() that calls
|
|
|
7711c0 |
qemu_sendv_packet_async() indirectly, they often ignore the return
|
|
|
7711c0 |
value. In this case qemu will just the drop packets if peer can't
|
|
|
7711c0 |
receive.
|
|
|
7711c0 |
|
|
|
7711c0 |
Qemu will copy the packet if it was queued. So it was safe for both
|
|
|
7711c0 |
kinds of the callers to assume the packet was sent.
|
|
|
7711c0 |
|
|
|
7711c0 |
Since we move the check from qemu_deliver_packet_iov() to
|
|
|
7711c0 |
qemu_sendv_packet_async(), it would be safer to make
|
|
|
7711c0 |
qemu_deliver_packet_iov() static to prevent any external user in the
|
|
|
7711c0 |
future.
|
|
|
7711c0 |
|
|
|
7711c0 |
This is a revised patch of CVE-2018-17963.
|
|
|
7711c0 |
|
|
|
7711c0 |
Cc: qemu-stable@nongnu.org
|
|
|
7711c0 |
Cc: Li Qiang <liq3ea@163.com>
|
|
|
7711c0 |
Fixes: 1592a9947036 ("net: ignore packet size greater than INT_MAX")
|
|
|
7711c0 |
Reported-by: Li Qiang <liq3ea@gmail.com>
|
|
|
7711c0 |
Reviewed-by: Li Qiang <liq3ea@gmail.com>
|
|
|
7711c0 |
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
|
|
7711c0 |
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
|
|
7711c0 |
Message-id: 20181204035347.6148-2-jasowang@redhat.com
|
|
|
7711c0 |
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
|
|
7711c0 |
(cherry picked from commit 25c01bd19d0e4b66f357618aeefda1ef7a41e21a)
|
|
|
7711c0 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7711c0 |
---
|
|
|
7711c0 |
include/net/net.h | 6 ------
|
|
|
7711c0 |
net/net.c | 28 +++++++++++++++++-----------
|
|
|
7711c0 |
2 files changed, 17 insertions(+), 17 deletions(-)
|
|
|
7711c0 |
|
|
|
7711c0 |
diff --git a/include/net/net.h b/include/net/net.h
|
|
|
7711c0 |
index 1f7341e..df4df25 100644
|
|
|
7711c0 |
--- a/include/net/net.h
|
|
|
7711c0 |
+++ b/include/net/net.h
|
|
|
7711c0 |
@@ -170,12 +170,6 @@ void qemu_check_nic_model(NICInfo *nd, const char *model);
|
|
|
7711c0 |
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
|
|
|
7711c0 |
const char *default_model);
|
|
|
7711c0 |
|
|
|
7711c0 |
-ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
|
|
7711c0 |
- unsigned flags,
|
|
|
7711c0 |
- const struct iovec *iov,
|
|
|
7711c0 |
- int iovcnt,
|
|
|
7711c0 |
- void *opaque);
|
|
|
7711c0 |
-
|
|
|
7711c0 |
void print_net_client(Monitor *mon, NetClientState *nc);
|
|
|
7711c0 |
void hmp_info_network(Monitor *mon, const QDict *qdict);
|
|
|
7711c0 |
void net_socket_rs_init(SocketReadState *rs,
|
|
|
7711c0 |
diff --git a/net/net.c b/net/net.c
|
|
|
7711c0 |
index c991243..6e5c335 100644
|
|
|
7711c0 |
--- a/net/net.c
|
|
|
7711c0 |
+++ b/net/net.c
|
|
|
7711c0 |
@@ -231,6 +231,11 @@ static void qemu_net_client_destructor(NetClientState *nc)
|
|
|
7711c0 |
{
|
|
|
7711c0 |
g_free(nc);
|
|
|
7711c0 |
}
|
|
|
7711c0 |
+static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
|
|
7711c0 |
+ unsigned flags,
|
|
|
7711c0 |
+ const struct iovec *iov,
|
|
|
7711c0 |
+ int iovcnt,
|
|
|
7711c0 |
+ void *opaque);
|
|
|
7711c0 |
|
|
|
7711c0 |
static void qemu_net_client_setup(NetClientState *nc,
|
|
|
7711c0 |
NetClientInfo *info,
|
|
|
7711c0 |
@@ -705,22 +710,18 @@ static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
|
|
|
7711c0 |
return ret;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
-ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
|
|
7711c0 |
- unsigned flags,
|
|
|
7711c0 |
- const struct iovec *iov,
|
|
|
7711c0 |
- int iovcnt,
|
|
|
7711c0 |
- void *opaque)
|
|
|
7711c0 |
+static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
|
|
7711c0 |
+ unsigned flags,
|
|
|
7711c0 |
+ const struct iovec *iov,
|
|
|
7711c0 |
+ int iovcnt,
|
|
|
7711c0 |
+ void *opaque)
|
|
|
7711c0 |
{
|
|
|
7711c0 |
NetClientState *nc = opaque;
|
|
|
7711c0 |
- size_t size = iov_size(iov, iovcnt);
|
|
|
7711c0 |
int ret;
|
|
|
7711c0 |
|
|
|
7711c0 |
- if (size > INT_MAX) {
|
|
|
7711c0 |
- return size;
|
|
|
7711c0 |
- }
|
|
|
7711c0 |
|
|
|
7711c0 |
if (nc->link_down) {
|
|
|
7711c0 |
- return size;
|
|
|
7711c0 |
+ return iov_size(iov, iovcnt);
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
if (nc->receive_disabled) {
|
|
|
7711c0 |
@@ -745,10 +746,15 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender,
|
|
|
7711c0 |
NetPacketSent *sent_cb)
|
|
|
7711c0 |
{
|
|
|
7711c0 |
NetQueue *queue;
|
|
|
7711c0 |
+ size_t size = iov_size(iov, iovcnt);
|
|
|
7711c0 |
int ret;
|
|
|
7711c0 |
|
|
|
7711c0 |
+ if (size > NET_BUFSIZE) {
|
|
|
7711c0 |
+ return size;
|
|
|
7711c0 |
+ }
|
|
|
7711c0 |
+
|
|
|
7711c0 |
if (sender->link_down || !sender->peer) {
|
|
|
7711c0 |
- return iov_size(iov, iovcnt);
|
|
|
7711c0 |
+ return size;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
/* Let filters handle the packet first */
|
|
|
7711c0 |
--
|
|
|
7711c0 |
1.8.3.1
|
|
|
7711c0 |
|