extensions: Preserve environment in auto-loaded extensions (#3101)

This commit is contained in:
Teddy Reed 2017-03-24 18:47:23 -07:00 committed by GitHub
parent 995648f337
commit f6f9480874
9 changed files with 57 additions and 79 deletions

View File

@ -117,7 +117,7 @@ std::shared_ptr<PlatformProcess> PlatformProcess::launchExtension(
const std::string& extensions_socket,
const std::string& extensions_timeout,
const std::string& extensions_interval,
const std::string& verbose) {
bool verbose) {
auto ext_pid = ::fork();
if (ext_pid < 0) {
return std::shared_ptr<PlatformProcess>();
@ -125,13 +125,13 @@ std::shared_ptr<PlatformProcess> PlatformProcess::launchExtension(
setEnvVar("OSQUERY_EXTENSION", std::to_string(::getpid()).c_str());
::execle(exec_path.c_str(),
("osquery extension: " + extension).c_str(),
(verbose) ? "--verbose" : "--noverbose",
"--socket",
extensions_socket.c_str(),
"--timeout",
extensions_timeout.c_str(),
"--interval",
extensions_interval.c_str(),
(verbose == "true") ? "--verbose" : (char*)nullptr,
(char*)nullptr,
::environ);

View File

@ -162,7 +162,7 @@ class PlatformProcess : private boost::noncopyable {
const std::string& extensions_socket,
const std::string& extensions_timeout,
const std::string& extensions_interval,
const std::string& verbose);
bool verbose = false);
/**
* @brief Launches a new Python script

View File

@ -1,43 +0,0 @@
/*
* 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.
*
*/
#pragma once
/// The following codes are specifically for checking whether the child worker
/// or extension process ran successfully. These values should be the values
/// captured as exit codes if all the child process checks complete without
/// deviation.
#define EXTENSION_SUCCESS_CODE 0x45
#define WORKER_SUCCESS_CODE 0x57
/// The following are error codes returned by the child process.
#define ERROR_COMPARE_ARGUMENT -1
#define ERROR_LAUNCHER_PROCESS -2
#define ERROR_QUERY_PROCESS_IMAGE -3
#define ERROR_IMAGE_NAME_LENGTH -4
#define ERROR_LAUNCHER_MISMATCH -5
namespace osquery {
/// Stores the path of the currently executing executable
extern std::string kProcessTestExecPath;
/// This is the expected module name of the launcher process.
extern const char *kOsqueryTestModuleName;
/// These are the expected arguments for our test worker process.
extern const char *kExpectedWorkerArgs[];
extern const size_t kExpectedWorkerArgsCount;
/// These are the expected arguments for our test extensions process.
extern const char *kExpectedExtensionArgs[];
extern const size_t kExpectedExtensionArgsCount;
}

View File

@ -13,7 +13,7 @@
#include <osquery/core.h>
#include "osquery/core/process.h"
#include "osquery/core/testing.h"
#include "osquery/tests/test_util.h"
namespace osquery {
@ -89,8 +89,7 @@ TEST_F(ProcessTests, test_constructorPosix) {
TEST_F(ProcessTests, test_getpid) {
int pid = -1;
std::shared_ptr<PlatformProcess> process =
PlatformProcess::getCurrentProcess();
auto process = PlatformProcess::getCurrentProcess();
EXPECT_NE(nullptr, process.get());
#ifdef WIN32
@ -123,13 +122,13 @@ TEST_F(ProcessTests, test_envVar) {
TEST_F(ProcessTests, test_launchExtension) {
{
std::shared_ptr<osquery::PlatformProcess> process =
osquery::PlatformProcess::launchExtension(kProcessTestExecPath.c_str(),
"extension-test",
kExpectedExtensionArgs[2],
kExpectedExtensionArgs[4],
kExpectedExtensionArgs[6],
"true");
auto process =
PlatformProcess::launchExtension(kProcessTestExecPath.c_str(),
"extension-test",
kExpectedExtensionArgs[3],
kExpectedExtensionArgs[5],
kExpectedExtensionArgs[7],
true);
EXPECT_NE(nullptr, process.get());
int code = 0;
@ -150,11 +149,10 @@ TEST_F(ProcessTests, test_launchWorker) {
}
argv.push_back(nullptr);
std::shared_ptr<osquery::PlatformProcess> process =
osquery::PlatformProcess::launchWorker(
kProcessTestExecPath.c_str(),
static_cast<int>(kExpectedWorkerArgsCount),
&argv[0]);
auto process = PlatformProcess::launchWorker(
kProcessTestExecPath.c_str(),
static_cast<int>(kExpectedWorkerArgsCount),
&argv[0]);
for (size_t i = 0; i < argv.size(); i++) {
delete[] argv[i];
}
@ -170,13 +168,13 @@ TEST_F(ProcessTests, test_launchWorker) {
#ifdef WIN32
TEST_F(ProcessTests, test_launchExtensionQuotes) {
{
std::shared_ptr<osquery::PlatformProcess> process =
osquery::PlatformProcess::launchExtension(kProcessTestExecPath.c_str(),
"exten\"sion-te\"st",
"socket-name",
"100",
"5",
"true");
auto process =
PlatformProcess::launchExtension(kProcessTestExecPath.c_str(),
"exten\"sion-te\"st",
"socket-name",
"100",
"5",
true);
EXPECT_NE(nullptr, process.get());
int code = 0;

View File

@ -14,8 +14,8 @@
#include <osquery/core.h>
#include <osquery/tables.h>
#include "osquery/core/testing.h"
#include "osquery/core/watcher.h"
#include "osquery/tests/test_util.h"
using namespace testing;

View File

@ -493,7 +493,7 @@ void WatcherRunner::createExtension(const std::string& extension) {
Flag::getValue("extensions_socket"),
Flag::getValue("extensions_timeout"),
Flag::getValue("extensions_interval"),
Flag::getValue("verbose"));
Flag::getValue("verbose") == "true");
if (ext_process == nullptr) {
// Unrecoverable error, cannot create an extension process.
LOG(ERROR) << "Cannot create extension process: " << extension;

View File

@ -242,7 +242,7 @@ std::shared_ptr<PlatformProcess> PlatformProcess::launchExtension(
const std::string& extensions_socket,
const std::string& extensions_timeout,
const std::string& extensions_interval,
const std::string& verbose) {
bool verbose) {
::STARTUPINFOA si = {0};
::PROCESS_INFORMATION pi = {nullptr};
@ -253,14 +253,11 @@ std::shared_ptr<PlatformProcess> PlatformProcess::launchExtension(
std::stringstream argv_stream;
argv_stream << "\"osquery extension: "
<< boost::replace_all_copy(extension, "\"", "") << "\" ";
argv_stream << ((verbose) ? "--verbose" : "--noverbose") << " ";
argv_stream << "--socket \"" << extensions_socket << "\" ";
argv_stream << "--timeout " << extensions_timeout << " ";
argv_stream << "--interval " << extensions_interval << " ";
if (verbose == "true") {
argv_stream << "--verbose";
}
// We don't directly use argv.c_str() as the value for lpCommandLine in
// CreateProcess since that argument requires a modifiable buffer. So,
// instead, we off-load the contents of argv into a vector which will have its

View File

@ -21,7 +21,6 @@
#include <osquery/logger.h>
#include "osquery/core/process.h"
#include "osquery/core/testing.h"
#include "osquery/tests/test_util.h"
namespace osquery {
@ -42,13 +41,13 @@ const size_t kExpectedWorkerArgsCount =
/// These are the expected arguments for our test extensions process.
const char* kExpectedExtensionArgs[] = {"osquery extension: extension-test",
"--verbose",
"--socket",
"socket-name",
"--timeout",
"100",
"--interval",
"5",
"--verbose",
nullptr};
const size_t kExpectedExtensionArgsCount =
(sizeof(osquery::kExpectedExtensionArgs) / sizeof(char*)) - 1;

View File

@ -25,6 +25,20 @@ namespace pt = boost::property_tree;
namespace osquery {
/// The following codes are specifically for checking whether the child worker
/// or extension process ran successfully. These values should be the values
/// captured as exit codes if all the child process checks complete without
/// deviation.
#define EXTENSION_SUCCESS_CODE 0x45
#define WORKER_SUCCESS_CODE 0x57
/// The following are error codes returned by the child process.
#define ERROR_COMPARE_ARGUMENT -1
#define ERROR_LAUNCHER_PROCESS -2
#define ERROR_QUERY_PROCESS_IMAGE -3
#define ERROR_IMAGE_NAME_LENGTH -4
#define ERROR_LAUNCHER_MISMATCH -5
/// Init function for tests and benchmarks.
void initTesting();
@ -46,6 +60,20 @@ extern std::string kTestDataPath;
extern std::string kTestWorkingDirectory;
extern std::string kFakeDirectory;
/// Stores the path of the currently executing executable
extern std::string kProcessTestExecPath;
/// This is the expected module name of the launcher process.
extern const char* kOsqueryTestModuleName;
/// These are the expected arguments for our test worker process.
extern const char* kExpectedWorkerArgs[];
extern const size_t kExpectedWorkerArgsCount;
/// These are the expected arguments for our test extensions process.
extern const char* kExpectedExtensionArgs[];
extern const size_t kExpectedExtensionArgsCount;
// Get an example generate config with one static source name to JSON content.
std::map<std::string, std::string> getTestConfigMap();
@ -65,7 +93,7 @@ QueryData getTestDBExpectedResults();
// Starting with the dataset returned by createTestDB(), getTestDBResultStream
// returns a vector of std::pair's where pair.first is the query that would
// need to be performed on the dataset to make the results be pair.second
std::vector<std::pair<std::string, QueryData> > getTestDBResultStream();
std::vector<std::pair<std::string, QueryData>> getTestDBResultStream();
// getSerializedRowColumnNames returns a vector of test column names that
// are in alphabetical order. If unordered_and_repeated is true, the
@ -129,4 +157,3 @@ void createMockFileStructure();
// remove the small directory structure used for testing
void tearDownMockFileStructure();
}