Blame SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch

7711c0
From d92a9042320bd959eac36dc76de9dc293d8da2ce Mon Sep 17 00:00:00 2001
7711c0
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
7711c0
Date: Mon, 20 May 2019 17:57:04 +0200
7711c0
Subject: [PATCH 3/3] slirp: don't manipulate so_rcv in tcp_emu()
7711c0
MIME-Version: 1.0
7711c0
Content-Type: text/plain; charset=UTF-8
7711c0
Content-Transfer-Encoding: 8bit
7711c0
7711c0
RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
7711c0
Message-id: <20190520175704.6250-4-marcandre.lureau@redhat.com>
7711c0
Patchwork-id: 88108
7711c0
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 3/3] slirp: don't manipulate so_rcv in tcp_emu()
7711c0
Bugzilla: 1669071
7711c0
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7711c0
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7711c0
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
7711c0
7711c0
For some reason, EMU_IDENT is not like other "emulated" protocols and
7711c0
tries to reconstitute the original buffer, if it came in multiple
7711c0
packets. Unfortunately, it does so wrongly, as it doesn't respect the
7711c0
sbuf circular buffer appending rules, nor does it maintain some of the
7711c0
invariants (rptr is incremented without bounds, etc): this leads to
7711c0
further memory corruption revealed by ASAN or various malloc
7711c0
errors. Furthermore, the so_rcv buffer is regularly flushed, so there
7711c0
is no guarantee that buffer reconstruction will do what is expected.
7711c0
7711c0
Instead, do what the function comment says: "XXX Assumes the whole
7711c0
command came in one packet", and don't touch so_rcv.
7711c0
7711c0
Related to: https://bugzilla.redhat.com/show_bug.cgi?id=1664205
7711c0
7711c0
Cc: Prasad J Pandit <pjp@fedoraproject.org>
7711c0
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
7711c0
7711c0
(cherry picked from libslirp commit
7711c0
9da0da837780f825b5db31db6620492f8b7cd5d6)
7711c0
7711c0
[ MA - backported with style conflicts, and without qemu commit
7711c0
a7104eda7dab99d0cdbd3595c211864cba415905 which is unnecessary with
7711c0
this patch ]
7711c0
7711c0
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
7711c0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
---
7711c0
 slirp/tcp_subr.c | 63 +++++++++++++++++++++++++++-----------------------------
7711c0
 1 file changed, 30 insertions(+), 33 deletions(-)
7711c0
7711c0
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
7711c0
index a801a14..0152f72 100644
7711c0
--- a/slirp/tcp_subr.c
7711c0
+++ b/slirp/tcp_subr.c
7711c0
@@ -636,42 +636,39 @@ tcp_emu(struct socket *so, struct mbuf *m)
7711c0
 			struct socket *tmpso;
7711c0
 			struct sockaddr_in addr;
7711c0
 			socklen_t addrlen = sizeof(struct sockaddr_in);
7711c0
-			struct sbuf *so_rcv = &so->so_rcv;
7711c0
-
7711c0
-			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
7711c0
-			so_rcv->sb_wptr += m->m_len;
7711c0
-			so_rcv->sb_rptr += m->m_len;
7711c0
-			m_inc(m, m->m_len + 1);
7711c0
-			m->m_data[m->m_len] = 0; /* NULL terminate */
7711c0
-			if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
7711c0
-				if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
7711c0
-					HTONS(n1);
7711c0
-					HTONS(n2);
7711c0
-					/* n2 is the one on our host */
7711c0
-					for (tmpso = slirp->tcb.so_next;
7711c0
-					     tmpso != &slirp->tcb;
7711c0
-					     tmpso = tmpso->so_next) {
7711c0
-						if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
7711c0
-						    tmpso->so_lport == n2 &&
7711c0
-						    tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
7711c0
-						    tmpso->so_fport == n1) {
7711c0
-							if (getsockname(tmpso->s,
7711c0
-								(struct sockaddr *)&addr, &addrlen) == 0)
7711c0
-							   n2 = addr.sin_port;
7711c0
-							break;
7711c0
-						}
7711c0
+			char *eol = g_strstr_len(m->m_data, m->m_len, "\r\n");
7711c0
+
7711c0
+			if (!eol) {
7711c0
+				return 1;
7711c0
+			}
7711c0
+
7711c0
+			*eol = '\0';
7711c0
+			if (sscanf(m->m_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
7711c0
+				HTONS(n1);
7711c0
+				HTONS(n2);
7711c0
+				/* n2 is the one on our host */
7711c0
+				for (tmpso = slirp->tcb.so_next; tmpso != &slirp->tcb;
7711c0
+					 tmpso = tmpso->so_next) {
7711c0
+					if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
7711c0
+						tmpso->so_lport == n2 &&
7711c0
+						tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
7711c0
+						tmpso->so_fport == n1) {
7711c0
+						if (getsockname(tmpso->s, (struct sockaddr *)&addr,
7711c0
+										&addrlen) == 0)
7711c0
+							n2 = addr.sin_port;
7711c0
+						break;
7711c0
 					}
7711c0
-					NTOHS(n1);
7711c0
-					NTOHS(n2);
7711c0
-					so_rcv->sb_cc = snprintf(so_rcv->sb_data,
7711c0
-								 so_rcv->sb_datalen,
7711c0
-								 "%d,%d\r\n", n1, n2);
7711c0
-					so_rcv->sb_rptr = so_rcv->sb_data;
7711c0
-					so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
7711c0
 				}
7711c0
+				NTOHS(n1);
7711c0
+				NTOHS(n2);
7711c0
+				m_inc(m, snprintf(NULL, 0, "%d,%d\r\n", n1, n2) + 1);
7711c0
+				m->m_len = snprintf(m->m_data, M_ROOM(m), "%d,%d\r\n", n1, n2);
7711c0
+				assert(m->m_len < M_ROOM(m));
7711c0
+			} else {
7711c0
+				*eol = '\r';
7711c0
 			}
7711c0
-			m_free(m);
7711c0
-			return 0;
7711c0
+
7711c0
+			return 1;
7711c0
 		}
7711c0
 
7711c0
         case EMU_FTP: /* ftp */
7711c0
-- 
7711c0
1.8.3.1
7711c0