aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-11-12 10:12:07 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-11-12 10:12:07 +0000
commit460f0236c12a86a38692c12d9bf8e2391dc10a77 (patch)
treea4a505288b3fa853c28f6edddefbe5d3c1fca74c
parent160e5c22e55b3f775c2003dfc626fa872ee4a7a1 (diff)
parent5c75f3adbbfcdf8fae6e74875b44efb8d928974a (diff)
Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging
slirp updates Peter Maydell (4): slirp: Don't pass possibly -1 fd to send() slirp: Use g_new() to allocate sockets in socreate() slirp: Remove code that handles socreate() failure slirp: fork_exec(): create and connect child socket before fork() # gpg: Signature made Sat 10 Nov 2018 14:08:53 GMT # gpg: using RSA key E3F65A9E9560DB4C # gpg: Good signature from "Samuel Thibault <samuel.thibault@aquilenet.fr>" # gpg: aka "Samuel Thibault <sthibault@debian.org>" # gpg: aka "Samuel Thibault <samuel.thibault@gnu.org>" # gpg: aka "Samuel Thibault <samuel.thibault@inria.fr>" # gpg: aka "Samuel Thibault <samuel.thibault@labri.fr>" # gpg: aka "Samuel Thibault <samuel.thibault@ens-lyon.org>" # gpg: aka "Samuel Thibault <samuel.thibault@u-bordeaux.fr>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 900C B024 B679 31D4 0F82 304B D017 8C76 7D06 9EE6 # Subkey fingerprint: 33FA 7B64 6195 01F8 CE9C 8F97 E3F6 5A9E 9560 DB4C * remotes/thibault/tags/samuel-thibault: slirp: fork_exec(): create and connect child socket before fork() slirp: Remove code that handles socreate() failure slirp: Use g_new() to allocate sockets in socreate() slirp: Don't pass possibly -1 fd to send() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--slirp/ip_icmp.c2
-rw-r--r--slirp/misc.c55
-rw-r--r--slirp/slirp.c14
-rw-r--r--slirp/socket.c17
-rw-r--r--slirp/tcp_input.c7
-rw-r--r--slirp/tcp_subr.c7
-rw-r--r--slirp/udp.c6
-rw-r--r--slirp/udp6.c3
8 files changed, 56 insertions, 55 deletions
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index da100d1f55..9210eef3f3 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -160,7 +160,7 @@ icmp_input(struct mbuf *m, int hlen)
} else {
struct socket *so;
struct sockaddr_storage addr;
- if ((so = socreate(slirp)) == NULL) goto freeit;
+ so = socreate(slirp);
if (icmp_send(so, m, hlen) == 0) {
return;
}
diff --git a/slirp/misc.c b/slirp/misc.c
index 260187b6b6..57bdd808e2 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -85,9 +85,10 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
int
fork_exec(struct socket *so, const char *ex, int do_pty)
{
- int s;
- struct sockaddr_in addr;
+ int s, cs;
+ struct sockaddr_in addr, csaddr;
socklen_t addrlen = sizeof(addr);
+ socklen_t csaddrlen = sizeof(csaddr);
int opt;
const char *argv[256];
/* don't want to clobber the original */
@@ -120,10 +121,35 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
}
}
+ if (getsockname(s, (struct sockaddr *)&csaddr, &csaddrlen) < 0) {
+ closesocket(s);
+ return 0;
+ }
+ cs = qemu_socket(AF_INET, SOCK_STREAM, 0);
+ if (cs < 0) {
+ closesocket(s);
+ return 0;
+ }
+ csaddr.sin_addr = loopback_addr;
+ /*
+ * This connect won't block because we've already listen()ed on
+ * the server end (even though we won't accept() the connection
+ * until later on).
+ */
+ do {
+ ret = connect(cs, (struct sockaddr *)&csaddr, csaddrlen);
+ } while (ret < 0 && errno == EINTR);
+ if (ret < 0) {
+ closesocket(s);
+ closesocket(cs);
+ return 0;
+ }
+
pid = fork();
switch(pid) {
case -1:
error_report("Error: fork failed: %s", strerror(errno));
+ closesocket(cs);
close(s);
return 0;
@@ -131,21 +157,10 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
setsid();
/* Set the DISPLAY */
- getsockname(s, (struct sockaddr *)&addr, &addrlen);
close(s);
- /*
- * Connect to the socket
- * XXX If any of these fail, we're in trouble!
- */
- s = qemu_socket(AF_INET, SOCK_STREAM, 0);
- addr.sin_addr = loopback_addr;
- do {
- ret = connect(s, (struct sockaddr *)&addr, addrlen);
- } while (ret < 0 && errno == EINTR);
-
- dup2(s, 0);
- dup2(s, 1);
- dup2(s, 2);
+ dup2(cs, 0);
+ dup2(cs, 1);
+ dup2(cs, 2);
for (s = getdtablesize() - 1; s >= 3; s--)
close(s);
@@ -178,12 +193,10 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
default:
qemu_add_child_watch(pid);
+ closesocket(cs);
/*
- * XXX this could block us...
- * XXX Should set a timer here, and if accept() doesn't
- * return after X seconds, declare it a failure
- * The only reason this will block forever is if socket()
- * of connect() fail in the child process
+ * This should never block, because we already connect()ed
+ * on the child end before we forked.
*/
do {
so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 51de41fc02..322edf51eb 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -1091,6 +1091,17 @@ ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
return len;
}
+ if (so->s == -1) {
+ /*
+ * This should in theory not happen but it is hard to be
+ * sure because some code paths will end up with so->s == -1
+ * on a failure but don't dispose of the struct socket.
+ * Check specifically, so we don't pass -1 to send().
+ */
+ errno = EBADF;
+ return -1;
+ }
+
return send(so->s, buf, len, flags);
}
@@ -1466,9 +1477,6 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
int ret;
struct socket *so = socreate(slirp);
- if (!so)
- return -ENOMEM;
-
ret = vmstate_load_state(f, &vmstate_slirp_socket, so, version_id);
if (ret < 0)
diff --git a/slirp/socket.c b/slirp/socket.c
index 322383a1f9..c01d8696af 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -46,17 +46,15 @@ struct socket *solookup(struct socket **last, struct socket *head,
struct socket *
socreate(Slirp *slirp)
{
- struct socket *so;
+ struct socket *so = g_new(struct socket, 1);
- so = (struct socket *)malloc(sizeof(struct socket));
- if(so) {
memset(so, 0, sizeof(struct socket));
so->so_state = SS_NOFDREF;
so->s = -1;
so->slirp = slirp;
so->pollfds_idx = -1;
- }
- return(so);
+
+ return so;
}
/*
@@ -110,7 +108,7 @@ sofree(struct socket *so)
if (so->so_tcpcb) {
free(so->so_tcpcb);
}
- free(so);
+ g_free(so);
}
size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
@@ -715,14 +713,11 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
DEBUG_ARG("flags = %x", flags);
so = socreate(slirp);
- if (!so) {
- return NULL;
- }
/* Don't tcp_attach... we don't need so_snd nor so_rcv */
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
- free(so);
- return NULL;
+ g_free(so);
+ return NULL;
}
insque(so, &slirp->tcb);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 07bcbdb2dd..d073ef9525 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -429,11 +429,10 @@ findso:
if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
goto dropwithreset;
- if ((so = socreate(slirp)) == NULL)
- goto dropwithreset;
+ so = socreate(slirp);
if (tcp_attach(so) < 0) {
- free(so); /* Not sofree (if it failed, it's not insqued) */
- goto dropwithreset;
+ g_free(so); /* Not sofree (if it failed, it's not insqued) */
+ goto dropwithreset;
}
sbreserve(&so->so_snd, TCP_SNDSPACE);
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 8d0f94b75f..fa61349cbb 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -469,13 +469,8 @@ void tcp_connect(struct socket *inso)
so = inso;
} else {
so = socreate(slirp);
- if (so == NULL) {
- /* If it failed, get rid of the pending connection */
- closesocket(accept(inso->s, (struct sockaddr *)&addr, &addrlen));
- return;
- }
if (tcp_attach(so) < 0) {
- free(so); /* NOT sofree */
+ g_free(so); /* NOT sofree */
return;
}
so->lhost = inso->lhost;
diff --git a/slirp/udp.c b/slirp/udp.c
index e5bf065bf2..c47870a61b 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -171,9 +171,6 @@ udp_input(register struct mbuf *m, int iphlen)
* create one
*/
so = socreate(slirp);
- if (!so) {
- goto bad;
- }
if (udp_attach(so, AF_INET) == -1) {
DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
errno,strerror(errno)));
@@ -331,9 +328,6 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
socklen_t addrlen = sizeof(struct sockaddr_in);
so = socreate(slirp);
- if (!so) {
- return NULL;
- }
so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
if (so->s < 0) {
sofree(so);
diff --git a/slirp/udp6.c b/slirp/udp6.c
index 7c4a6b003a..986010f0d3 100644
--- a/slirp/udp6.c
+++ b/slirp/udp6.c
@@ -91,9 +91,6 @@ void udp6_input(struct mbuf *m)
if (so == NULL) {
/* If there's no socket for this packet, create one. */
so = socreate(slirp);
- if (!so) {
- goto bad;
- }
if (udp_attach(so, AF_INET6) == -1) {
DEBUG_MISC((dfd, " udp6_attach errno = %d-%s\n",
errno, strerror(errno)));