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