Skip to content

Commit

Permalink
Close all the fds of the child before exec
Browse files Browse the repository at this point in the history
This patch closes all the fds (starting from 3) of
the child before exec in InstanceTask.

Please see the bug description for more details.

Change-Id: I9f18f88c9c58540ad6358a2a989f344f60be86d8
Closes-bug: #1394300
  • Loading branch information
numansiddique authored and divakardhar committed Feb 3, 2015
1 parent fa8101b commit 519e6c5
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/vnsw/agent/cmn/agent_cmn.h
Expand Up @@ -9,6 +9,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/address.h>
#include <unistd.h>

#include <boost/intrusive_ptr.hpp>
#include <boost/bind.hpp>
Expand Down Expand Up @@ -73,6 +74,13 @@ static inline void CfgUuidSet(uint64_t ms_long, uint64_t ls_long,
}
}

static inline void CloseTaskFds(void) {
int max_open_fds = sysconf(_SC_OPEN_MAX);
int fd;
for(fd = 3; fd < max_open_fds; fd++)
close(fd);
}

extern SandeshTraceBufferPtr OperDBTraceBuf;
extern bool GetBuildInfo(std::string &build_info_str);

Expand Down
2 changes: 2 additions & 0 deletions src/vnsw/agent/oper/instance_task.cc
Expand Up @@ -93,6 +93,8 @@ pid_t InstanceTask::Run() {
close(STDOUT_FILENO);
close(STDIN_FILENO);

/* Close all the open fds before execvp */
CloseTaskFds();
execvp(c_argv[0], (char **) c_argv.data());
perror("execvp");

Expand Down
1 change: 1 addition & 0 deletions src/vnsw/agent/oper/instance_task.h
Expand Up @@ -9,6 +9,7 @@
#include "base/timer.h"
#include "base/queue_task.h"
#include "cmn/agent_signal.h"
#include "cmn/agent_cmn.h"
#include "db/db_entry.h"

class EventManager;
Expand Down
1 change: 1 addition & 0 deletions src/vnsw/agent/oper/test/SConscript
Expand Up @@ -22,6 +22,7 @@ test_fabric_interface = AgentEnv.MakeTestCmd(env, 'test_fabric_interface',
oper_flaky_test_suite)
test_aap = AgentEnv.MakeTestCmd(env, 'test_aap', oper_flaky_test_suite)
test_ipv6 = AgentEnv.MakeTestCmd(env, 'test_ipv6', oper_test_suite)
test_instance_task = AgentEnv.MakeTestCmd(env, 'test_instance_task', oper_test_suite)
env.Alias('agent:test_ipv6', test_ipv6)

env.Append(LIBPATH = [
Expand Down
94 changes: 94 additions & 0 deletions src/vnsw/agent/oper/test/test_instance_task.cc
@@ -0,0 +1,94 @@
#include "oper/instance_task.h"
#include "testing/gunit.h"

#include <boost/filesystem.hpp>
#include <boost/bind.hpp>
#include <sstream>
#include <fstream>

#include <cstdlib>
#include <boost/uuid/random_generator.hpp>

#include "io/event_manager.h"
#include "base/logging.h"
#include "base/os.h"
#include "base/test/task_test_util.h"

using namespace std;
using namespace boost::filesystem;

class InstanceTaskFdTest : public ::testing::Test {
public:
virtual void SetUp() {
memset(tmpfilename, 0, sizeof(tmpfilename));
strcpy(tmpfilename, "task_fd_XXXXXX");
mkstemp(tmpfilename);
std::fstream testfile(tmpfilename);
testfile << "while true; do sleep 1; done";
testfile.close();
std::stringstream cmd_str;
cmd_str << "/bin/sh" << " " <<tmpfilename;
task_ = new InstanceTask(cmd_str.str(), 1, &evm);
}

virtual void TearDown() {
delete task_;
remove(tmpfilename);
}

int StartTask() {
/* create few fds */
if(pipe(pipe_fds) == -1)
return -1;
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0)
return -1;
/* run the task now */
task_pid = task_->Run();
return task_pid;
}

int StopTask() {
task_->Stop();
close(pipe_fds[0]);
close(pipe_fds[1]);
close(sock_fd);
}

int GetTaskFds() {
std::stringstream proc_path;
int no_of_fds;
proc_path << "/proc/" <<task_pid<<"/fd/";
path the_path(proc_path.str());
no_of_fds = std::count_if(directory_iterator(the_path),
directory_iterator(),
bind( static_cast<bool(*)(const path&)>(is_other),
bind( &directory_entry::path, _1)));
return no_of_fds;
}

protected:
int pipe_fds[2];
int sock_fd;
InstanceTask *task_;
int task_pid;
EventManager evm;
char tmpfilename[L_tmpnam];
};

TEST_F(InstanceTaskFdTest, TestCloseTaskFds) {
task_pid = StartTask();
EXPECT_TRUE(task_pid > 0);
int task_open_fds = GetTaskFds();
StopTask();
/* The task should have only 1 opened fd (i.e fd 2) */
EXPECT_EQ(1U, task_open_fds);
};

int main(int argc, char **argv) {
LoggingInit();
::testing::InitGoogleTest(&argc, argv);

int result = RUN_ALL_TESTS();
return result;
}
4 changes: 4 additions & 0 deletions src/vnsw/agent/uve/vm_stat.cc
Expand Up @@ -5,6 +5,7 @@
#include <sys/times.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <uve/vm_stat.h>
#include <uve/vm_stat_data.h>
#include <db/db.h>
Expand Down Expand Up @@ -87,6 +88,9 @@ void VmStat::ExecCmd(std::string cmd, DoneCb cb) {
dup2(out[1], STDOUT_FILENO);
//Close out[1] as stdout is a exact replica of out[1]
close(out[1]);

/* Close all the open fds before execvp */
CloseTaskFds();
execvp(argv[0], argv);
perror("execvp");
exit(127);
Expand Down

0 comments on commit 519e6c5

Please sign in to comment.