Blame SOURCES/kvm-net-drop-too-large-packet-early.patch

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