blob: 5bacd674813eba808b92eaf5ac527d119f0d7171 [file] [log] [blame]
Andrew Geisslerc926e172021-05-07 16:11:35 -05001From 4b1988a29d67277d6c8ce1df52975f5616592913 Mon Sep 17 00:00:00 2001
2From: Jason Wang <jasowang@redhat.com>
3Date: Wed, 24 Feb 2021 11:44:36 +0800
4Subject: [PATCH 01/10] net: introduce qemu_receive_packet()
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Some NIC supports loopback mode and this is done by calling
10nc->info->receive() directly which in fact suppresses the effort of
11reentrancy check that is done in qemu_net_queue_send().
12
13Unfortunately we can't use qemu_net_queue_send() here since for
14loopback there's no sender as peer, so this patch introduce a
15qemu_receive_packet() which is used for implementing loopback mode
16for a NIC with this check.
17
18NIC that supports loopback mode will be converted to this helper.
19
20This is intended to address CVE-2021-3416.
21
22Cc: Prasad J Pandit <ppandit@redhat.com>
23Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
24Cc: qemu-stable@nongnu.org
25Signed-off-by: Jason Wang <jasowang@redhat.com>
26
27Upstream-Status: Backport [705df5466c98f3efdd2b68d3b31dad86858acad7]
28CVE: CVE-2021-3416
29
30Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
31---
32 include/net/net.h | 5 +++++
33 include/net/queue.h | 8 ++++++++
34 net/net.c | 38 +++++++++++++++++++++++++++++++-------
35 net/queue.c | 22 ++++++++++++++++++++++
36 4 files changed, 66 insertions(+), 7 deletions(-)
37
38diff --git a/include/net/net.h b/include/net/net.h
39index 778fc787c..03f058ecb 100644
40--- a/include/net/net.h
41+++ b/include/net/net.h
42@@ -143,12 +143,17 @@ void *qemu_get_nic_opaque(NetClientState *nc);
43 void qemu_del_net_client(NetClientState *nc);
44 typedef void (*qemu_nic_foreach)(NICState *nic, void *opaque);
45 void qemu_foreach_nic(qemu_nic_foreach func, void *opaque);
46+int qemu_can_receive_packet(NetClientState *nc);
47 int qemu_can_send_packet(NetClientState *nc);
48 ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov,
49 int iovcnt);
50 ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov,
51 int iovcnt, NetPacketSent *sent_cb);
52 ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size);
53+ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size);
54+ssize_t qemu_receive_packet_iov(NetClientState *nc,
55+ const struct iovec *iov,
56+ int iovcnt);
57 ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size);
58 ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
59 int size, NetPacketSent *sent_cb);
60diff --git a/include/net/queue.h b/include/net/queue.h
61index c0269bb1d..9f2f289d7 100644
62--- a/include/net/queue.h
63+++ b/include/net/queue.h
64@@ -55,6 +55,14 @@ void qemu_net_queue_append_iov(NetQueue *queue,
65
66 void qemu_del_net_queue(NetQueue *queue);
67
68+ssize_t qemu_net_queue_receive(NetQueue *queue,
69+ const uint8_t *data,
70+ size_t size);
71+
72+ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
73+ const struct iovec *iov,
74+ int iovcnt);
75+
76 ssize_t qemu_net_queue_send(NetQueue *queue,
77 NetClientState *sender,
78 unsigned flags,
79diff --git a/net/net.c b/net/net.c
80index 6a2c3d956..5e15e5d27 100644
81--- a/net/net.c
82+++ b/net/net.c
83@@ -528,6 +528,17 @@ int qemu_set_vnet_be(NetClientState *nc, bool is_be)
84 #endif
85 }
86
87+int qemu_can_receive_packet(NetClientState *nc)
88+{
89+ if (nc->receive_disabled) {
90+ return 0;
91+ } else if (nc->info->can_receive &&
92+ !nc->info->can_receive(nc)) {
93+ return 0;
94+ }
95+ return 1;
96+}
97+
98 int qemu_can_send_packet(NetClientState *sender)
99 {
100 int vm_running = runstate_is_running();
101@@ -540,13 +551,7 @@ int qemu_can_send_packet(NetClientState *sender)
102 return 1;
103 }
104
105- if (sender->peer->receive_disabled) {
106- return 0;
107- } else if (sender->peer->info->can_receive &&
108- !sender->peer->info->can_receive(sender->peer)) {
109- return 0;
110- }
111- return 1;
112+ return qemu_can_receive_packet(sender->peer);
113 }
114
115 static ssize_t filter_receive_iov(NetClientState *nc,
116@@ -679,6 +684,25 @@ ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
117 return qemu_send_packet_async(nc, buf, size, NULL);
118 }
119
120+ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size)
121+{
122+ if (!qemu_can_receive_packet(nc)) {
123+ return 0;
124+ }
125+
126+ return qemu_net_queue_receive(nc->incoming_queue, buf, size);
127+}
128+
129+ssize_t qemu_receive_packet_iov(NetClientState *nc, const struct iovec *iov,
130+ int iovcnt)
131+{
132+ if (!qemu_can_receive_packet(nc)) {
133+ return 0;
134+ }
135+
136+ return qemu_net_queue_receive_iov(nc->incoming_queue, iov, iovcnt);
137+}
138+
139 ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
140 {
141 return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
142diff --git a/net/queue.c b/net/queue.c
143index 19e32c80f..c872d51df 100644
144--- a/net/queue.c
145+++ b/net/queue.c
146@@ -182,6 +182,28 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
147 return ret;
148 }
149
150+ssize_t qemu_net_queue_receive(NetQueue *queue,
151+ const uint8_t *data,
152+ size_t size)
153+{
154+ if (queue->delivering) {
155+ return 0;
156+ }
157+
158+ return qemu_net_queue_deliver(queue, NULL, 0, data, size);
159+}
160+
161+ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
162+ const struct iovec *iov,
163+ int iovcnt)
164+{
165+ if (queue->delivering) {
166+ return 0;
167+ }
168+
169+ return qemu_net_queue_deliver_iov(queue, NULL, 0, iov, iovcnt);
170+}
171+
172 ssize_t qemu_net_queue_send(NetQueue *queue,
173 NetClientState *sender,
174 unsigned flags,
175--
1762.29.2
177