From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.1 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 7238 invoked from network); 14 Mar 2021 16:04:56 -0000 Received: from mother.openwall.net (195.42.179.200) by inbox.vuxu.org with ESMTPUTF8; 14 Mar 2021 16:04:56 -0000 Received: (qmail 11909 invoked by uid 550); 14 Mar 2021 16:04:51 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 11879 invoked from network); 14 Mar 2021 16:04:51 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=opensmtpd; bh=WTfUBieMSY z0J8pbrRZRSvAAKr/BsPbRYr+vTopfY9E=; h=from:subject:to:date; d=soeren-tempel.net; b=HijEiPzSnWHilQy7gMwaYLIaLwFbcxd6V4a3iIq7WY3AqGP cmTU0GURwCAdgDIKFr1UpXuSxi5/FaB9N++gv7Sp5lsyZJD1TPlek9zulZGmR8iAxQLzkt i7PPkyvH39HNlHndBOILyMhI/Y/NZF6BRp8TZ3Piyo51Wfo4RFQ3A8= Date: Sun, 14 Mar 2021 17:04:34 +0100 To: musl@lists.openwall.com From: =?UTF-8?Q?S=C3=B6ren?= Tempel Message-Id: <2HXA7ZPT82TJK.2KFTHDGNA32X6@8pit.net> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [musl] popen needs to close streams created by previous calls Hi, This is a follow-up to a discussion from IRC regarding a bug in popen(). The POSIX specification for popen() mandates the following [1]: > The popen() function shall ensure that any streams from previous > popen() calls that remain open in the parent process are closed in the > new child process. Currently, musl's popen() implementation does not adhere to this requirement. When multiple popen() calls are used in an application, newly created child processes will inherit the file descriptors for the reading/writing end of pipes created by previous popen() calls. This can lead to pclose() deadlocks when popen() has been used to create multiples pipes which can be written to. As one would need to close the writing end in all created child processes to cause an EOF on the reading end [2]. Other implementations (e.g. glibc [3] or uclibc [4]) maintain an internal list of pipes created by previous popen() calls and close them in the child process created by popen(). Something similar will likely be needed for musl as well. On IRC, duncaen proposed the following patch to resolve this issue: diff --git a/src/stdio/popen.c b/src/stdio/popen.c index 92cb57ee..7233b08f 100644 --- a/src/stdio/popen.c +++ b/src/stdio/popen.c @@ -50,6 +50,12 @@ FILE *popen(const char *cmd, const char *mode) e =3D ENOMEM; if (!posix_spawn_file_actions_init(&fa)) { + for (FILE *f=3D*__ofl_lock(); f; f=3Df->next) + if (f->pipe_pid && posix_spawn_file_actions_addclose(&fa, f->fd)) { + __ofl_unlock(); + goto fail; + } + __ofl_unlock(); if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) { if (!(e =3D posix_spawn(&pid, "/bin/sh", &fa, 0, (char *[]){ "sh", "-c", (char *)cmd, 0 }, __environ))) { Further changes to the proposed patch could be discussed in this thread. Greetings, S=C3=B6ren [1]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html [2]: https://github.com/leahneukirchen/mblaze/issues/203 [3]: https://sourceware.org/git/?p=3Dglibc.git;a=3Dblob;f=3Dlibio/iopopen.c= ;h=3D3afca7e173ef74eaf937b243b06ae40c2a590ec9#l63 [4]: https://git.uclibc.org/uClibc/tree/libc/stdio/popen.c?id=3D9b0f7d99899= bf96510a4c3ea84218b7efb50f696#n88