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