From nobody Thu Nov 6 14:26:02 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1541518284257876.2564496187683; Tue, 6 Nov 2018 07:31:24 -0800 (PST) Received: from localhost ([::1]:41699 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gK3K6-0003uz-Ho for importer@patchew.org; Tue, 06 Nov 2018 10:31:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39708) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gK3HL-00022q-B8 for qemu-devel@nongnu.org; Tue, 06 Nov 2018 10:28:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gK3HK-0006xI-CH for qemu-devel@nongnu.org; Tue, 06 Nov 2018 10:28:31 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:52368) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gK3HK-0006vv-40 for qemu-devel@nongnu.org; Tue, 06 Nov 2018 10:28:30 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1gK32n-0007y7-US; Tue, 06 Nov 2018 15:13:29 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Tue, 6 Nov 2018 15:13:23 +0000 Message-Id: <20181106151323.16154-5-peter.maydell@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181106151323.16154-1-peter.maydell@linaro.org> References: <20181106151323.16154-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH for-3.1 4/4] slirp: fork_exec(): create and connect child socket before fork() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Samuel Thibault , Jan Kiszka , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Currently fork_exec() fork()s, and then creates and connects the child socket which it uses for communication with the parent in the child process. This is awkward because the child has no mechanism to report failure back to the parent, which might end up blocked forever in accept(). The child code also has an issue pointed out by Coverity (CID 1005727), where if the qemu_socket() call fails it will pass -1 as a file descriptor to connect(). Fix these issues by moving the creation of the child's end of the socket to before the fork(), where we are in a position to handle a possible failure. Signed-off-by: Peter Maydell --- slirp/misc.c | 55 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/slirp/misc.c b/slirp/misc.c index 260187b6b62..57bdd808e2d 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 =3D sizeof(addr); + socklen_t csaddrlen =3D 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_p= ty) } } =20 + if (getsockname(s, (struct sockaddr *)&csaddr, &csaddrlen) < 0) { + closesocket(s); + return 0; + } + cs =3D qemu_socket(AF_INET, SOCK_STREAM, 0); + if (cs < 0) { + closesocket(s); + return 0; + } + csaddr.sin_addr =3D 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 =3D connect(cs, (struct sockaddr *)&csaddr, csaddrlen); + } while (ret < 0 && errno =3D=3D EINTR); + if (ret < 0) { + closesocket(s); + closesocket(cs); + return 0; + } + pid =3D fork(); switch(pid) { case -1: error_report("Error: fork failed: %s", strerror(errno)); + closesocket(cs); close(s); return 0; =20 @@ -131,21 +157,10 @@ fork_exec(struct socket *so, const char *ex, int do_p= ty) setsid(); =20 /* 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 =3D qemu_socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr =3D loopback_addr; - do { - ret =3D connect(s, (struct sockaddr *)&addr, addrlen); - } while (ret < 0 && errno =3D=3D EINTR); - - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); + dup2(cs, 0); + dup2(cs, 1); + dup2(cs, 2); for (s =3D getdtablesize() - 1; s >=3D 3; s--) close(s); =20 @@ -178,12 +193,10 @@ fork_exec(struct socket *so, const char *ex, int do_p= ty) =20 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 =3D accept(s, (struct sockaddr *)&addr, &addrlen= ); --=20 2.19.1