From patchwork Sun Sep 13 13:44:50 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Navid Rahimi X-Patchwork-Id: 8662 Received: (qmail 51563 invoked by alias); 13 Sep 2015 13:44:57 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 51548 invoked by uid 89); 13 Sep 2015 13:44:56 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.8 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-la0-f45.google.com MIME-Version: 1.0 X-Received: by 10.152.2.130 with SMTP id 2mr4931951lau.121.1442151891107; Sun, 13 Sep 2015 06:44:51 -0700 (PDT) Date: Sun, 13 Sep 2015 18:14:50 +0430 Message-ID: Subject: [PATCH v2] [BZ 18433] Check posix_spawn return value in case of failure From: navid Rahimi To: GNU C Library Using pipe approach to check status of child.The vfork usage (in the spawni function) is more restricted therefore pipe approach would be better. I use fallback (combination of pipe and fcntl with FD_CLOEXEC) mode for platform which does not support pipe2. diff --git a/ChangeLog b/ChangeLog index eb731cc..b8a1efb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-13 Navid Rahimi + + [BZ #18433] + * sysdeps/posix/spawni.c (__spawni): Check child status. + 2015-09-12 Rasmus Villemoes * sysdeps/unix/sysv/linux/getsysstats.c (__get_phys_pages): diff --git a/sysdeps/posix/spawni.c b/sysdeps/posix/spawni.c index eee9331..8994216 100644 --- a/sysdeps/posix/spawni.c +++ b/sysdeps/posix/spawni.c @@ -89,6 +89,24 @@ __spawni (pid_t *pid, const char *file, char *path, *p, *name; size_t len; size_t pathlen; + int pipefd[2]; + + errno = 0; + /* Open Read/Write pipe for parent/child communication. */ +#ifdef __ASSUME_PIPE2 + if (__pipe2 (pipefd, O_CLOEXEC)) + return errno; +#else + if (__pipe (pipefd)) + return errno; + if (__fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) == -1 + || __fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) == -1) + { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } +#endif /* Do this once. */ short int flags = attrp == NULL ? 0 : attrp->__flags; @@ -109,20 +127,26 @@ __spawni (pid_t *pid, const char *file, if (new_pid != 0) { - if (new_pid < 0) + __close (pipefd[1]); + if (new_pid < 0){ + __close (pipefd[0]); return errno; - + } /* The call was successful. Store the PID if necessary. */ if (pid != NULL) *pid = new_pid; - return 0; + __read (pipefd[0], &errno, sizeof errno); + __close (pipefd[0]); + return errno; } + else + __close (pipefd[0]); /* Set signal mask. */ if ((flags & POSIX_SPAWN_SETSIGMASK) != 0 && __sigprocmask (SIG_SETMASK, &attrp->__ss, NULL) != 0) - _exit (SPAWN_ERROR); + goto fail; /* Set signal default action. */ if ((flags & POSIX_SPAWN_SETSIGDEF) != 0) @@ -140,7 +164,7 @@ __spawni (pid_t *pid, const char *file, for (sig = 1; sig <= _NSIG; ++sig) if (__sigismember (&attrp->__sd, sig) != 0 && __sigaction (sig, &sa, NULL) != 0) - _exit (SPAWN_ERROR); + goto fail; } @@ -150,25 +174,25 @@ __spawni (pid_t *pid, const char *file, == POSIX_SPAWN_SETSCHEDPARAM) { if (__sched_setparam (0, &attrp->__sp) == -1) - _exit (SPAWN_ERROR); + goto fail; } else if ((flags & POSIX_SPAWN_SETSCHEDULER) != 0) { if (__sched_setscheduler (0, attrp->__policy, &attrp->__sp) == -1) - _exit (SPAWN_ERROR); + goto fail; } #endif /* Set the process group ID. */ if ((flags & POSIX_SPAWN_SETPGROUP) != 0 && __setpgid (0, attrp->__pgrp) != 0) - _exit (SPAWN_ERROR); + goto fail; /* Set the effective user and group IDs. */ if ((flags & POSIX_SPAWN_RESETIDS) != 0 && (local_seteuid (__getuid ()) != 0 || local_setegid (__getgid ()) != 0)) - _exit (SPAWN_ERROR); + goto fail; /* Execute the file actions. */ if (file_actions != NULL) @@ -196,7 +220,7 @@ __spawni (pid_t *pid, const char *file, if (action->action.close_action.fd < 0 || action->action.close_action.fd >= fdlimit.rlim_cur) /* Signal the error. */ - _exit (SPAWN_ERROR); + goto fail; } break; @@ -209,7 +233,7 @@ __spawni (pid_t *pid, const char *file, if (new_fd == -1) /* The `open' call failed. */ - _exit (SPAWN_ERROR); + goto fail; /* Make sure the desired file descriptor is used. */ if (new_fd != action->action.open_action.fd) @@ -217,11 +241,11 @@ __spawni (pid_t *pid, const char *file, if (__dup2 (new_fd, action->action.open_action.fd) != action->action.open_action.fd) /* The `dup2' call failed. */ - _exit (SPAWN_ERROR); + goto fail; if (close_not_cancel (new_fd) != 0) /* The `close' call failed. */ - _exit (SPAWN_ERROR); + goto fail; } } break; @@ -231,7 +255,7 @@ __spawni (pid_t *pid, const char *file, action->action.dup2_action.newfd) != action->action.dup2_action.newfd) /* The `dup2' call failed. */ - _exit (SPAWN_ERROR); + goto fail; break; } } @@ -245,7 +269,7 @@ __spawni (pid_t *pid, const char *file, maybe_script_execute (file, argv, envp, xflags); /* Oh, oh. `execve' returns. This is bad. */ - _exit (SPAWN_ERROR); + goto fail; } /* We have to search for FILE on the path. */ @@ -304,11 +328,15 @@ __spawni (pid_t *pid, const char *file, /* Some other error means we found an executable file, but something went wrong executing it; return the error to our caller. */ - _exit (SPAWN_ERROR); + goto fail; } } while (*p++ != '\0'); + fail: + /* Send parent what was the reason of failure. */ + __write (pipefd[1], &errno, sizeof errno); + __close (pipefd[1]); /* Return with an error. */ _exit (SPAWN_ERROR); }