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