2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-03 07:25:18 +00:00

[#1680] check executable flags on ProcessSpawn constructor

This commit is contained in:
Razvan Becheriu
2021-04-29 15:48:07 +03:00
parent 1648292ae7
commit 89efd60e9a
4 changed files with 25 additions and 70 deletions

View File

@@ -35,9 +35,6 @@ RunScriptImpl::configure(LibraryHandle& handle) {
IOServicePtr io_service(new asiolink::IOService()); IOServicePtr io_service(new asiolink::IOService());
try { try {
ProcessSpawn process(io_service, name->stringValue()); ProcessSpawn process(io_service, name->stringValue());
if (!process.checkPermissions()) {
isc_throw(InvalidParameter, "The 'name' parameter must point to an executable");
}
} catch (const isc::Exception& ex) { } catch (const isc::Exception& ex) {
isc_throw(InvalidParameter, "Invalid 'name' parameter: " << ex.what()); isc_throw(InvalidParameter, "Invalid 'name' parameter: " << ex.what());
} }

View File

@@ -132,12 +132,6 @@ public:
/// @param pid A process pid. /// @param pid A process pid.
void clearState(const pid_t pid); void clearState(const pid_t pid);
/// @brief Check executable permissions.
///
/// @return true if file has executable permissions, false otherwise.
/// @throw ProcessSpawnError if file does not exist.
bool checkPermissions() const;
private: private:
/// @brief Copies the argument specified as a C++ string to the new /// @brief Copies the argument specified as a C++ string to the new
@@ -204,6 +198,16 @@ ProcessSpawnImpl::ProcessSpawnImpl(IOServicePtr io_service,
io_signal_set_(new IOSignalSet(io_service, io_signal_set_(new IOSignalSet(io_service,
std::bind(&ProcessSpawnImpl::waitForProcess, std::bind(&ProcessSpawnImpl::waitForProcess,
ph::_1))) { ph::_1))) {
struct stat st;
if (stat(executable_.c_str(), &st)) {
isc_throw(ProcessSpawnError, "File not found: " << executable_);
}
if (!(st.st_mode & S_IEXEC)) {
isc_throw(ProcessSpawnError, "File not executable: " << executable_);
}
io_signal_set_->add(SIGCHLD); io_signal_set_->add(SIGCHLD);
// Conversion of the arguments to the C-style array we start by setting // Conversion of the arguments to the C-style array we start by setting
@@ -357,18 +361,6 @@ ProcessSpawnImpl::clearState(const pid_t pid) {
} }
} }
bool
ProcessSpawnImpl::checkPermissions() const {
struct stat st;
if (stat(executable_.c_str(), &st)) {
isc_throw(ProcessSpawnError, "File not found: " << executable_);
}
if (st.st_mode & S_IEXEC) {
return (true);
}
return (false);
}
ProcessSpawn::ProcessSpawn(IOServicePtr io_service, ProcessSpawn::ProcessSpawn(IOServicePtr io_service,
const std::string& executable, const std::string& executable,
const ProcessArgs& args, const ProcessArgs& args,
@@ -406,10 +398,5 @@ ProcessSpawn::clearState(const pid_t pid) {
return (impl_->clearState(pid)); return (impl_->clearState(pid));
} }
bool
ProcessSpawn::checkPermissions() const {
return (impl_->checkPermissions());
}
} // namespace asiolink } // namespace asiolink
} // namespace isc } // namespace isc

View File

@@ -137,12 +137,6 @@ public:
/// @param pid A process pid. /// @param pid A process pid.
void clearState(const pid_t pid); void clearState(const pid_t pid);
/// @brief Check executable permissions.
///
/// @return true if file has executable permissions, false otherwise.
/// @throw ProcessSpawnError if file does not exist.
bool checkPermissions() const;
private: private:
/// @brief A smart pointer to the implementation of this class. /// @brief A smart pointer to the implementation of this class.

View File

@@ -261,27 +261,17 @@ TEST_F(ProcessSpawnTest, spawnNoArgs) {
// This test verifies that the EXIT_FAILURE code is returned when // This test verifies that the EXIT_FAILURE code is returned when
// application can't be executed. // application can't be executed.
TEST_F(ProcessSpawnTest, invalidExecutable) { TEST_F(ProcessSpawnTest, invalidExecutable) {
ProcessSpawn process(io_service_, "foo"); std::string expected = "File not found: foo";
pid_t pid = 0; ASSERT_THROW_MSG(ProcessSpawn process(io_service_, "foo"),
ASSERT_NO_THROW(pid = process.spawn()); ProcessSpawnError, expected);
// Set test fail safe. std::string name = TEST_SCRIPT_SH;
setTestTime(1000); name += ".in";
// The next handler executed is IOSignal's handler. expected = "File not executable: ";
io_service_->run_one(); expected += name;
ASSERT_THROW_MSG(ProcessSpawn process(io_service_, name),
// The first handler executed is the IOSignal's internal timer expire ProcessSpawnError, expected);
// callback.
io_service_->run_one();
// Polling once to be sure.
io_service_->poll();
ASSERT_EQ(1, processed_signals_.size());
ASSERT_EQ(SIGCHLD, processed_signals_[0]);
EXPECT_EQ(EXIT_FAILURE, process.getExitStatus(pid));
} }
// This test verifies that the full command line for the process is // This test verifies that the full command line for the process is
@@ -299,14 +289,16 @@ TEST_F(ProcessSpawnTest, getCommandLine) {
args.push_back("-y"); args.push_back("-y");
args.push_back("foo"); args.push_back("foo");
args.push_back("bar"); args.push_back("bar");
ProcessSpawn process(io_service_, "myapp", args); ProcessSpawn process(io_service_, TEST_SCRIPT_SH, args);
EXPECT_EQ("myapp -x -y foo bar", process.getCommandLine()); std::string expected = TEST_SCRIPT_SH;
expected += " -x -y foo bar";
EXPECT_EQ(expected, process.getCommandLine());
} }
{ {
// Case 2: no arguments. // Case 2: no arguments.
ProcessSpawn process(io_service_, "myapp"); ProcessSpawn process(io_service_, TEST_SCRIPT_SH);
EXPECT_EQ("myapp", process.getCommandLine()); EXPECT_EQ(TEST_SCRIPT_SH, process.getCommandLine());
} }
} }
@@ -345,19 +337,4 @@ TEST_F(ProcessSpawnTest, isRunning) {
ASSERT_EQ(SIGCHLD, processed_signals_[0]); ASSERT_EQ(SIGCHLD, processed_signals_[0]);
} }
// This test verifies that the checkPermissions function throws if the file does
// not exist and returns true or false if the file is or it is not executable.
TEST_F(ProcessSpawnTest, checkPermissions) {
ProcessSpawn no_process(io_service_, "no-file");
EXPECT_THROW_MSG(no_process.checkPermissions(), ProcessSpawnError,
"File not found: no-file");
std::string name = TEST_SCRIPT_SH;
name += ".in";
ProcessSpawn invalid_process(io_service_, name);
ASSERT_FALSE(invalid_process.checkPermissions());
ProcessSpawn process(io_service_, TEST_SCRIPT_SH);
ASSERT_TRUE(process.checkPermissions());
}
} // end of anonymous namespace } // end of anonymous namespace