fixed #549: Memory allocation is not safe between fork() and execve()

This commit is contained in:
Guenter Obiltschnig 2014-11-19 16:56:01 +01:00
parent 7b11e14624
commit b620c25278

View File

@ -149,6 +149,20 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env) ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
{ {
// We must not allocated memory after fork(),
// therefore allocate all required buffers first.
std::vector<char> envChars = getEnvironmentVariablesBuffer(env);
std::vector<char*> argv(args.size() + 2);
int i = 0;
argv[i++] = const_cast<char*>(command.c_str());
for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it)
{
argv[i++] = const_cast<char*>(it->c_str());
}
argv[i] = NULL;
const char* pInitialDirectory = initialDirectory.empty() ? 0 : initialDirectory.c_str();
int pid = fork(); int pid = fork();
if (pid < 0) if (pid < 0)
{ {
@ -156,15 +170,22 @@ ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command,
} }
else if (pid == 0) else if (pid == 0)
{ {
if (!initialDirectory.empty()) if (pInitialDirectory)
{ {
if (chdir(initialDirectory.c_str()) != 0) if (chdir(pInitialDirectory) != 0)
{ {
_exit(72); _exit(72);
} }
} }
setEnvironmentVariables(env); // set environment variables
char* p = &envChars[0];
while (*p)
{
putenv(p);
while (*p) ++p;
++p;
}
// setup redirection // setup redirection
if (inPipe) if (inPipe)
@ -179,15 +200,11 @@ ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command,
if (errPipe) errPipe->close(Pipe::CLOSE_BOTH); if (errPipe) errPipe->close(Pipe::CLOSE_BOTH);
// close all open file descriptors other than stdin, stdout, stderr // close all open file descriptors other than stdin, stdout, stderr
for (int i = 3; i < getdtablesize(); ++i) for (int i = 3; i < getdtablesize(); ++i)
{
close(i); close(i);
}
char** argv = new char*[args.size() + 2]; execvp(argv[0], &argv[0]);
int i = 0;
argv[i++] = const_cast<char*>(command.c_str());
for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it)
argv[i++] = const_cast<char*>(it->c_str());
argv[i] = NULL;
execvp(command.c_str(), argv);
_exit(72); _exit(72);
} }