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