If execve fails in logging mode, pass the errno directly to the grandparent

on the backchannel and exit.  The immediate parent will get SIGCHLD and
try to report that status but its parent will no longer be listening.
It would probably be cleaner to pass this over a pipe in script_child().
This commit is contained in:
Todd C. Miller
2010-04-13 06:31:55 -04:00
parent f321a85815
commit e472e4ae01

View File

@@ -599,6 +599,9 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
break; break;
} }
} }
if (!log_io)
continue;
if (FD_ISSET(sv[0], fdsw)) { if (FD_ISSET(sv[0], fdsw)) {
for (n = 0; n < NSIG; n++) { for (n = 0; n < NSIG; n++) {
if (!recvsig[n]) if (!recvsig[n])
@@ -616,9 +619,6 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
} }
} }
} }
if (!log_io)
continue;
if (FD_ISSET(script_fds[SFD_USERTTY], fdsr)) { if (FD_ISSET(script_fds[SFD_USERTTY], fdsr)) {
n = read(script_fds[SFD_USERTTY], input.buf + input.len, n = read(script_fds[SFD_USERTTY], input.buf + input.len,
sizeof(input.buf) - input.len); sizeof(input.buf) - input.len);
@@ -836,7 +836,10 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
/* setup tty and exec command */ /* setup tty and exec command */
script_run(path, argv, envp, rbac); script_run(path, argv, envp, rbac);
warning("unable to execute %s", path); /* XXX - leave this to plugin? */ warning("unable to execute %s", path); /* XXX - leave this to plugin? */
goto bad; cstat.type = CMD_ERRNO;
cstat.val = errno;
send(backchannel, &cstat, sizeof(cstat), 0);
_exit(1);
} }
/* /*
@@ -874,9 +877,17 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
do { do {
n = send(backchannel, &cstat, sizeof(cstat), 0); n = send(backchannel, &cstat, sizeof(cstat), 0);
} while (n == -1 && errno == EINTR); } while (n == -1 && errno == EINTR);
if (n != sizeof(cstat)) if (n != sizeof(cstat)) {
break; /* XXX - error, kill child and exit */ /*
sudo_debug(8, "sent wait status to parent"); * If child failed to exec it sends its own status
* which will result in ECONNRERFUSED here.
* XXX - treat other errno as fatal
*/
sudo_debug(8, "unable to send wait status: %s",
strerror(errno));
} else {
sudo_debug(8, "sent wait status to parent");
}
if (!WIFSTOPPED(status)) { if (!WIFSTOPPED(status)) {
/* XXX */ /* XXX */
_exit(1); /* child dead */ _exit(1); /* child dead */