libzfs: run_process: set O_NONBLOCK on lines pipe

Without this, we can deadlock: the child is stuck writing to the pipe,
and we are stuck waiting on the child

With this, we the child fills up the pipe (a few hundred kBish)
and starts getting EAGAINs, which allows it to either crash
or ignore them

libzfs_run_process_get_stdout*() is used only by zpool -c scripts,
which output short runs of K=V pairs, so the likelihood of losing
legitimate data there is relatively low

Reviewed-by: John Kennedy <john.kennedy@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12082
This commit is contained in:
наб 2021-05-19 13:56:24 +02:00 committed by Brian Behlendorf
parent e72383825b
commit 30dadd5c04
1 changed files with 3 additions and 2 deletions

View File

@ -889,7 +889,7 @@ libzfs_run_process_impl(const char *path, char *argv[], char *env[], int flags,
* Setup a pipe between our child and parent process if we're
* reading stdout.
*/
if ((lines != NULL) && pipe2(link, O_CLOEXEC) == -1)
if (lines != NULL && pipe2(link, O_NONBLOCK | O_CLOEXEC) == -1)
return (-EPIPE);
pid = vfork();
@ -928,7 +928,8 @@ libzfs_run_process_impl(const char *path, char *argv[], char *env[], int flags,
int status;
while ((error = waitpid(pid, &status, 0)) == -1 &&
errno == EINTR) { }
errno == EINTR)
;
if (error < 0 || !WIFEXITED(status))
return (-1);