|
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 |
|