if (flags != 0)
return errAuthorizationInvalidFlags;
- // create the mailbox file
- FILE *mbox = tmpfile();
- if (!mbox)
- return errAuthorizationInternal;
- if (fwrite(extForm, sizeof(*extForm), 1, mbox) != 1) {
- fclose(mbox);
- return errAuthorizationInternal;
- }
- fflush(mbox);
-
// compute the argument vector here because we can't allocate memory once we fork.
- // make text representation of the temp-file descriptor
- char mboxFdText[20];
- snprintf(mboxFdText, sizeof(mboxFdText), "auth %d", fileno(mbox));
-
// where is the trampoline?
#if defined(NDEBUG)
const char *trampoline = TRAMPOLINE;
trampoline = TRAMPOLINE;
#endif //NDEBUG
- const char **argv = argVector(trampoline, pathToTool, mboxFdText, arguments);
+ // make a data exchange pipe
+ int dataPipe[2];
+ if (pipe(dataPipe)) {
+ secinfo("authexec", "data pipe failure");
+ return errAuthorizationToolExecuteFailure;
+ }
+
+ // make text representation of the pipe handle
+ char pipeFdText[20];
+ snprintf(pipeFdText, sizeof(pipeFdText), "auth %d", dataPipe[READ]);
+ const char **argv = argVector(trampoline, pathToTool, pipeFdText, arguments);
// make a notifier pipe
int notify[2];
if (pipe(notify)) {
- fclose(mbox);
+ close(dataPipe[READ]); close(dataPipe[WRITE]);
+ if(argv) {
+ free(argv);
+ }
+ secinfo("authexec", "notify pipe failure");
return errAuthorizationToolExecuteFailure;
}
int comm[2];
if (communicationsPipe && socketpair(AF_UNIX, SOCK_STREAM, 0, comm)) {
close(notify[READ]); close(notify[WRITE]);
- fclose(mbox);
+ close(dataPipe[READ]); close(dataPipe[WRITE]);
+ if(argv) {
+ free(argv);
+ }
+ secinfo("authexec", "comm pipe failure");
return errAuthorizationToolExecuteFailure;
}
}
secinfo("authexec", "fork failed (errno=%d)", errno);
close(notify[READ]); close(notify[WRITE]);
- return errAuthorizationToolExecuteFailure;
+ status = errAuthorizationToolExecuteFailure;
+ goto exit_point;
default: { // parent
// close foreign side of pipes
close(notify[WRITE]);
if (communicationsPipe)
close(comm[WRITE]);
-
- // close mailbox file (child has it open now)
- fclose(mbox);
-
+
+ close(dataPipe[READ]);
+ if (write(dataPipe[WRITE], extForm, sizeof(*extForm)) != sizeof(*extForm)) {
+ secinfo("authexec", "fwrite data failed (errno=%d)", errno);
+ status = errAuthorizationInternal;
+ close(notify[READ]);
+ close(dataPipe[WRITE]);
+ if (communicationsPipe) {
+ close(comm[READ]);
+ close(comm[WRITE]);
+ }
+ goto exit_point;
+ }
+ close(dataPipe[WRITE]);
// get status notification from child
secinfo("authexec", "parent waiting for status");
ssize_t rc = read(notify[READ], &status, sizeof(status));
case sizeof(status): // read succeeded: child reported an error
secinfo("authexec", "parent received status=%d", (int)status);
close(notify[READ]);
- if (communicationsPipe) { close(comm[READ]); close(comm[WRITE]); }
+ close(dataPipe[WRITE]);
+ if (communicationsPipe) {
+ close(comm[READ]);
+ close(comm[WRITE]);
+ }
goto exit_point;
case 0: // end of file: exec succeeded
close(notify[READ]);
+ close(dataPipe[WRITE]);
if (communicationsPipe)
*communicationsPipe = fdopen(comm[READ], "r+");
secinfo("authexec", "parent resumes (no error)");
goto exit_point;
}
}
- break;
case 0: // child
// close foreign side of pipes
close(notify[READ]);
if (communicationsPipe)
close(comm[READ]);
-
+
+ // close write end of the data PIPE
+ close(dataPipe[WRITE]);
+
// fd 1 (stdout) holds the notify write end
dup2(notify[WRITE], 1);
close(notify[WRITE]);
// execute failed - tell the parent
{
+ // in case of failure, close read end of the data pipe as well
+ close(dataPipe[WRITE]);
+ close(dataPipe[READ]);
OSStatus error = errAuthorizationToolExecuteFailure;
error = h2n(error);
write(1, &error, sizeof(error));