2016-05-11 21:16:32 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
#include <osquery/core.h>
|
|
|
|
|
|
|
|
#include "osquery/core/process.h"
|
2017-03-25 01:47:23 +00:00
|
|
|
#include "osquery/tests/test_util.h"
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
|
|
|
/// Unlike checkChildProcessStatus, this will block until process exits.
|
2016-09-12 16:46:52 +00:00
|
|
|
static bool getProcessExitCode(osquery::PlatformProcess& process,
|
|
|
|
int& exitCode) {
|
2016-05-11 21:16:32 +00:00
|
|
|
if (!process.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
DWORD code = 0;
|
|
|
|
DWORD ret = 0;
|
|
|
|
|
|
|
|
while ((ret = ::WaitForSingleObject(process.nativeHandle(), INFINITE)) !=
|
|
|
|
WAIT_FAILED &&
|
|
|
|
ret != WAIT_OBJECT_0)
|
|
|
|
;
|
|
|
|
if (ret == WAIT_FAILED) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!::GetExitCodeProcess(process.nativeHandle(), &code)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (code != STILL_ACTIVE) {
|
|
|
|
exitCode = code;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
int status = 0;
|
|
|
|
if (::waitpid(process.nativeHandle(), &status, 0) == -1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (WIFEXITED(status)) {
|
|
|
|
exitCode = WEXITSTATUS(status);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
class ProcessTests : public testing::Test {};
|
|
|
|
|
|
|
|
TEST_F(ProcessTests, test_constructor) {
|
|
|
|
auto p = PlatformProcess(kInvalidPid);
|
|
|
|
EXPECT_FALSE(p.isValid());
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
TEST_F(ProcessTests, test_constructorWin) {
|
|
|
|
HANDLE handle =
|
|
|
|
::OpenProcess(PROCESS_ALL_ACCESS, FALSE, ::GetCurrentProcessId());
|
2016-10-21 18:20:28 +00:00
|
|
|
EXPECT_NE(handle, reinterpret_cast<HANDLE>(nullptr));
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
auto p = PlatformProcess(handle);
|
|
|
|
EXPECT_TRUE(p.isValid());
|
|
|
|
EXPECT_NE(p.nativeHandle(), handle);
|
|
|
|
|
|
|
|
if (handle) {
|
|
|
|
::CloseHandle(handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
TEST_F(ProcessTests, test_constructorPosix) {
|
|
|
|
auto p = PlatformProcess(getpid());
|
|
|
|
EXPECT_TRUE(p.isValid());
|
|
|
|
EXPECT_EQ(p.nativeHandle(), getpid());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TEST_F(ProcessTests, test_getpid) {
|
|
|
|
int pid = -1;
|
|
|
|
|
2017-03-25 01:47:23 +00:00
|
|
|
auto process = PlatformProcess::getCurrentProcess();
|
2016-09-12 16:46:52 +00:00
|
|
|
EXPECT_NE(nullptr, process.get());
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
pid = (int)::GetCurrentProcessId();
|
|
|
|
#else
|
|
|
|
pid = getpid();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
EXPECT_EQ(process->pid(), pid);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ProcessTests, test_envVar) {
|
|
|
|
auto val = getEnvVar("GTEST_OSQUERY");
|
|
|
|
EXPECT_FALSE(val);
|
2016-05-14 02:47:45 +00:00
|
|
|
EXPECT_FALSE(val.is_initialized());
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
EXPECT_TRUE(setEnvVar("GTEST_OSQUERY", "true"));
|
|
|
|
|
|
|
|
val = getEnvVar("GTEST_OSQUERY");
|
2016-05-14 02:47:45 +00:00
|
|
|
EXPECT_FALSE(!val);
|
|
|
|
EXPECT_TRUE(val.is_initialized());
|
2016-05-11 21:16:32 +00:00
|
|
|
EXPECT_EQ(*val, "true");
|
|
|
|
|
|
|
|
EXPECT_TRUE(unsetEnvVar("GTEST_OSQUERY"));
|
|
|
|
|
|
|
|
val = getEnvVar("GTEST_OSQUERY");
|
|
|
|
EXPECT_FALSE(val);
|
2016-05-14 02:47:45 +00:00
|
|
|
EXPECT_FALSE(val.is_initialized());
|
2016-05-11 21:16:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ProcessTests, test_launchExtension) {
|
|
|
|
{
|
2017-03-25 01:47:23 +00:00
|
|
|
auto process =
|
|
|
|
PlatformProcess::launchExtension(kProcessTestExecPath.c_str(),
|
|
|
|
"extension-test",
|
|
|
|
kExpectedExtensionArgs[3],
|
|
|
|
kExpectedExtensionArgs[5],
|
|
|
|
kExpectedExtensionArgs[7],
|
|
|
|
true);
|
2016-09-12 16:46:52 +00:00
|
|
|
EXPECT_NE(nullptr, process.get());
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
int code = 0;
|
|
|
|
EXPECT_TRUE(getProcessExitCode(*process, code));
|
|
|
|
EXPECT_EQ(code, EXTENSION_SUCCESS_CODE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ProcessTests, test_launchWorker) {
|
|
|
|
{
|
2016-09-12 16:46:52 +00:00
|
|
|
std::vector<char*> argv;
|
2016-05-14 02:47:45 +00:00
|
|
|
for (size_t i = 0; i < kExpectedWorkerArgsCount; i++) {
|
2016-09-12 16:46:52 +00:00
|
|
|
char* entry = new char[strlen(kExpectedWorkerArgs[i]) + 1];
|
2016-05-14 02:47:45 +00:00
|
|
|
EXPECT_NE(entry, nullptr);
|
|
|
|
memset(entry, '\0', strlen(kExpectedWorkerArgs[i]) + 1);
|
|
|
|
memcpy(entry, kExpectedWorkerArgs[i], strlen(kExpectedWorkerArgs[i]));
|
|
|
|
argv.push_back(entry);
|
|
|
|
}
|
|
|
|
argv.push_back(nullptr);
|
|
|
|
|
2017-03-25 01:47:23 +00:00
|
|
|
auto process = PlatformProcess::launchWorker(
|
|
|
|
kProcessTestExecPath.c_str(),
|
|
|
|
static_cast<int>(kExpectedWorkerArgsCount),
|
|
|
|
&argv[0]);
|
2016-05-14 02:47:45 +00:00
|
|
|
for (size_t i = 0; i < argv.size(); i++) {
|
2016-09-21 17:52:52 +00:00
|
|
|
delete[] argv[i];
|
2016-05-14 02:47:45 +00:00
|
|
|
}
|
|
|
|
|
2016-09-12 16:46:52 +00:00
|
|
|
EXPECT_NE(nullptr, process.get());
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
int code = 0;
|
|
|
|
EXPECT_TRUE(getProcessExitCode(*process, code));
|
|
|
|
EXPECT_EQ(code, WORKER_SUCCESS_CODE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
TEST_F(ProcessTests, test_launchExtensionQuotes) {
|
|
|
|
{
|
2017-03-25 01:47:23 +00:00
|
|
|
auto process =
|
|
|
|
PlatformProcess::launchExtension(kProcessTestExecPath.c_str(),
|
|
|
|
"exten\"sion-te\"st",
|
|
|
|
"socket-name",
|
|
|
|
"100",
|
|
|
|
"5",
|
|
|
|
true);
|
2016-09-12 16:46:52 +00:00
|
|
|
EXPECT_NE(nullptr, process.get());
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
int code = 0;
|
|
|
|
EXPECT_TRUE(getProcessExitCode(*process, code));
|
|
|
|
EXPECT_EQ(code, EXTENSION_SUCCESS_CODE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|