From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp11.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id tEAuKlfoj2KssAAAbAwnHQ (envelope-from ) for ; Thu, 26 May 2022 22:51:35 +0200 Received: from aspmx1.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp11.migadu.com with LMTPS id kDogKVfoj2KRhgAA9RJhRA (envelope-from ) for ; Thu, 26 May 2022 22:51:35 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 4A86DF3A5 for ; Thu, 26 May 2022 22:51:35 +0200 (CEST) Received: from localhost ([::1]:39964 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nuKSD-0004ii-QR for larch@yhetil.org; Thu, 26 May 2022 16:51:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:45592) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nuKRl-0004Yz-Ey for bug-guix@gnu.org; Thu, 26 May 2022 16:51:05 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:38019) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nuKRi-0001Ky-Ed for bug-guix@gnu.org; Thu, 26 May 2022 16:51:03 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nuKRi-0005ln-AF for bug-guix@gnu.org; Thu, 26 May 2022 16:51:02 -0400 X-Loop: help-debbugs@gnu.org Subject: bug#55441: [PATCH 1/2] Fix child spawning closing standard fds prematurely Resent-From: Josselin Poiret Original-Sender: "Debbugs-submit" Resent-CC: bug-guix@gnu.org Resent-Date: Thu, 26 May 2022 20:51:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 55441 X-GNU-PR-Package: guix X-GNU-PR-Keywords: To: Ludovic =?UTF-8?Q?Court=C3=A8s?= , Christopher Baines Cc: 55441@debbugs.gnu.org, Josselin Poiret Received: via spool by 55441-submit@debbugs.gnu.org id=B55441.165359825522153 (code B ref 55441); Thu, 26 May 2022 20:51:02 +0000 Received: (at 55441) by debbugs.gnu.org; 26 May 2022 20:50:55 +0000 Received: from localhost ([127.0.0.1]:60146 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nuKRa-0005lD-P0 for submit@debbugs.gnu.org; Thu, 26 May 2022 16:50:55 -0400 Received: from jpoiret.xyz ([206.189.101.64]:49004) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nuKRY-0005kz-IL for 55441@debbugs.gnu.org; Thu, 26 May 2022 16:50:53 -0400 Received: from authenticated-user (jpoiret.xyz [206.189.101.64]) by jpoiret.xyz (Postfix) with ESMTPA id 85933184F6C; Thu, 26 May 2022 20:50:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jpoiret.xyz; s=dkim; t=1653598251; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OW5G34BGS52mVKO3cQqsmLZEBpDsOcbo7KLGJEeipfk=; b=eP3xvCwxG4dQSsGhevRjiiXzrSYaI0sVZkT1dfkzB4bDfQjd0ScoSJFLQDZOa5TlvnqaMp LXmUjv/OtQhWRrBSkrcuMhNmpW2TUB696zCbIZqJTIjZLF4+X9mq6NToaQNongXaMZ2LjG 7Vr0PpGDvnAFg2kSSdySnsooK0n2wyYwqNe0/VFEFBg537pUT50/FDuewmadlezHz+ptry grkALWdFKVJ+5ooi0mV7Z4VImv8DKqliluJVMwelEepi/wJFeuP7wvYk1RDfOlgErwWbj5 bsdr0lGS7gS7mBCRwoW7HA2qNzB2C0yhLjT2N7aXt9CXiRGK63n6TRqTEh5S3w== Date: Thu, 26 May 2022 22:50:46 +0200 Message-Id: <20220526205047.23960-1-dev@jpoiret.xyz> In-Reply-To: <87sfow10lc.fsf@jpoiret.xyz> References: <87sfow10lc.fsf@jpoiret.xyz> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spamd-Bar: / X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-guix@gnu.org List-Id: Bug reports for GNU Guix List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-guix-bounces+larch=yhetil.org@gnu.org Sender: "bug-Guix" Reply-to: Josselin Poiret From: Josselin Poiret via Bug reports for GNU Guix X-Migadu-Flow: FLOW_IN X-Migadu-To: larch@yhetil.org X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1653598295; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=OW5G34BGS52mVKO3cQqsmLZEBpDsOcbo7KLGJEeipfk=; b=OASCLqZedlQ9EJIVFjAQf0NqSRLWyu8hRaQ673tvm2B6X932KkxRm1pJC36PaOc92xKhq2 5Tj4JOUhy2e48swQse6Z379wVmLMoa4aByCY2O1gWn38/eSOM7KG+VA/gOxXyWUap9ATOF SvPokDnuB3+h6d3pO0CwhfPf9fXKPzLLwkhwT3EVU3QYhIsdTzNFz26D/BlwdvxOwLJ0Ke C7LEQuqSgA4w6af2r0XqmjKfcw3xsJ38RJpcM7mYjoeljEEU3t5WZYRblu+XSbswMO+mmE FSfpNIwS5qUqRSCxHlhy4dq7b5FW2P9bM8aeRleorJVGhhUSWrlG1RdgIA/fFA== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1653598295; a=rsa-sha256; cv=none; b=mL+/8rE1TXw2t4pohw3bGPMfO+zwdACQ9oBg0lAa3PpkrwKz4lMLl+Y8m3plXu8ex8vNMp gNI/Mj1kxm2iNZzHrurKsAhUc2Hnr7lgX+e7XjMze1N6UL/dWDwG74teJoz5BjaoOTadmL 7gXxjBES8P1xebpKVcEucIR4HXprW5O+LeJap9KaJrpUMb2QrE5RHalc0RIPumTImOcbyw BmLODvtxlHFz99WSu65tU5ko7xqXF5O51GlYR8HR0zin9efTXZfXRMW03eSpklvjLbVoVp K0QxIdPsYEsCtSYzjFFrG8yWKEhOQp7D7p+rvUIswIveQCFDAwKGWCfRT7eABQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=jpoiret.xyz header.s=dkim header.b=eP3xvCwx; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of "bug-guix-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="bug-guix-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: -2.34 Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=jpoiret.xyz header.s=dkim header.b=eP3xvCwx; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of "bug-guix-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="bug-guix-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: 4A86DF3A5 X-Spam-Score: -2.34 X-Migadu-Scanner: scn0.migadu.com X-TUID: BK0Wy9dt84MP * libguile/posix.c (renumber_file_descriptor): Refactor it as dup_handle_error. (dup_handle_error, dup2_handle_error): New functions that wrap around dup and dup2 by retrying on EINTR or EBUSY, as well as erroring out on other errors. (start_child): Close standard file descriptors only after all of them have been dup2'd. --- libguile/posix.c | 82 +++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/libguile/posix.c b/libguile/posix.c index 3ab12b99e..dc3080b3c 100644 --- a/libguile/posix.c +++ b/libguile/posix.c @@ -1280,14 +1280,14 @@ SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0, #endif /* HAVE_FORK */ #ifdef HAVE_FORK -/* 'renumber_file_descriptor' is a helper function for 'start_child' - below, and is specialized for that particular environment where it - doesn't make sense to report errors via exceptions. It uses dup(2) - to duplicate the file descriptor FD, closes the original FD, and - returns the new descriptor. If dup(2) fails, print an error message - to ERR and abort. */ +/* 'dup_handle_error' is a helper function for 'start_child' below, and + is specialized for that particular environment where it doesn't make + sense to report errors via exceptions. It uses dup(2) to duplicate + the file descriptor FD, does *not* close the original FD, and returns + the new descriptor. If dup(2) fails, print an error message to ERR + and abort. */ static int -renumber_file_descriptor (int fd, int err) +dup_handle_error (int fd, int err) { int new_fd; @@ -1304,7 +1304,33 @@ renumber_file_descriptor (int fd, int err) _exit (127); /* Use exit status 127, as with other exec errors. */ } - close (fd); + return new_fd; +} + +/* 'dup2_handle_error' is a helper function for 'start_child' below, and + is specialized for that particular environment where it doesn't make + sense to report errors via exceptions. It uses dup2(2) to duplicate + the file descriptor FD, does *not* close the original FD, and returns + the new descriptor. If dup2(2) fails, print an error message to ERR + and abort. */ +static int +dup2_handle_error (int fd, int to, int err) +{ + int new_fd; + + do + new_fd = dup2 (fd, to); + while (new_fd == -1 && (errno == EINTR || errno == EBUSY)); + + if (new_fd == -1) + { + /* At this point we are in the child process before exec. We + cannot safely raise an exception in this environment. */ + const char *msg = strerror (errno); + fprintf (fdopen (err, "a"), "start_child: dup failed: %s\n", msg); + _exit (127); /* Use exit status 127, as with other exec errors. */ + } + return new_fd; } #endif /* HAVE_FORK */ @@ -1357,27 +1383,25 @@ start_child (const char *exec_file, char **exec_argv, if (err == -1) err = open ("/dev/null", O_WRONLY); - if (in > 0) - { - if (out == 0) - out = renumber_file_descriptor (out, err); - if (err == 0) - err = renumber_file_descriptor (err, err); - do dup2 (in, 0); while (errno == EINTR); - close (in); - } - if (out > 1) - { - if (err == 1) - err = renumber_file_descriptor (err, err); - do dup2 (out, 1); while (errno == EINTR); - close (out); - } - if (err > 2) - { - do dup2 (err, 2); while (errno == EINTR); - close (err); - } + /* Dup each non-yet-dup2'd fd that's in the way to the next available fd, + so that we can safely dup2 to 0/1/2 without potentially overwriting + in/out/err. Note that dup2 doesn't do anything if its arguments are + equal. */ + if (out == 0) + out = dup_handle_error (out, err); + if (err == 0) + err = dup_handle_error (err, err); + dup2_handle_error (in, 0, err); + + if (err == 1) + err = dup_handle_error (err, err); + dup2_handle_error (out, 1, err); + + dup2_handle_error (err, 2, err); + + if (in > 2) close (in); + if (out > 2) close (out); + if (err > 2) close (err); execvp (exec_file, exec_argv); -- 2.36.0