diff options
author | Peter Maydell | 2018-11-12 11:12:07 +0100 |
---|---|---|
committer | Peter Maydell | 2018-11-12 11:12:07 +0100 |
commit | 460f0236c12a86a38692c12d9bf8e2391dc10a77 (patch) | |
tree | a4a505288b3fa853c28f6edddefbe5d3c1fca74c /slirp/misc.c | |
parent | Merge remote-tracking branch 'remotes/gkurz/tags/for-upstream' into staging (diff) | |
parent | slirp: fork_exec(): create and connect child socket before fork() (diff) | |
download | qemu-460f0236c12a86a38692c12d9bf8e2391dc10a77.tar.gz qemu-460f0236c12a86a38692c12d9bf8e2391dc10a77.tar.xz qemu-460f0236c12a86a38692c12d9bf8e2391dc10a77.zip |
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>
Diffstat (limited to 'slirp/misc.c')
-rw-r--r-- | slirp/misc.c | 55 |
1 files changed, 34 insertions, 21 deletions
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); |