It's bad hygiene to just assume dup2(), close() and signal() will succeed.
Check all return values.
(Exit with status 126 on the new error branches for consistency with the
child process fcntl() -- and other syscall -- error modes in
"generator/states-connect-socket-activation.c".
See also these links, provided by Rich:
<
https://listman.redhat.com/archives/libguestfs/2019-September/022737.html>,
<
https://listman.redhat.com/archives/libguestfs/2019-September/022739.html>,
<
https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html>.)
Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
Reviewed-by: Richard W.M. Jones <rjones(a)redhat.com>
---
Notes:
v4:
- pick up Rich's R-b
- explain the use of exit status 126 in the commit message [Rich]
context:-U10
generator/states-connect.c | 22 +++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/generator/states-connect.c b/generator/states-connect.c
index 19c33f367519..750f8b765578 100644
--- a/generator/states-connect.c
+++ b/generator/states-connect.c
@@ -262,29 +262,41 @@ CONNECT_COMMAND.START:
pid = fork ();
if (pid == -1) {
SET_NEXT_STATE (%.DEAD);
set_error (errno, "fork");
close (sv[0]);
close (sv[1]);
return 0;
}
if (pid == 0) { /* child - run command */
- close (sv[0]);
- dup2 (sv[1], STDIN_FILENO);
- dup2 (sv[1], STDOUT_FILENO);
+ if (close (sv[0]) == -1) {
+ nbd_internal_fork_safe_perror ("close");
+ _exit (126);
+ }
+ if (dup2 (sv[1], STDIN_FILENO) == -1 ||
+ dup2 (sv[1], STDOUT_FILENO) == -1) {
+ nbd_internal_fork_safe_perror ("dup2");
+ _exit (126);
+ }
NBD_INTERNAL_FORK_SAFE_ASSERT (sv[1] != STDIN_FILENO);
NBD_INTERNAL_FORK_SAFE_ASSERT (sv[1] != STDOUT_FILENO);
- close (sv[1]);
+ if (close (sv[1]) == -1) {
+ nbd_internal_fork_safe_perror ("close");
+ _exit (126);
+ }
/* Restore SIGPIPE back to SIG_DFL. */
- signal (SIGPIPE, SIG_DFL);
+ if (signal (SIGPIPE, SIG_DFL) == SIG_ERR) {
+ nbd_internal_fork_safe_perror ("signal");
+ _exit (126);
+ }
execvp (h->argv.ptr[0], h->argv.ptr);
nbd_internal_fork_safe_perror (h->argv.ptr[0]);
if (errno == ENOENT)
_exit (127);
else
_exit (126);
}
/* Parent. */