watcher: Do not initialize the config in watcher (#3403)

This commit is contained in:
Teddy Reed 2017-06-13 17:26:34 -07:00 committed by GitHub
parent 4f7abe963d
commit f8f5718297
9 changed files with 56 additions and 22 deletions

9
.watchmanconfig Normal file
View File

@ -0,0 +1,9 @@
{
"ignore_dirs": [
"build",
],
"content_hash_warming": true,
"content_hash_max_items": 333333,
"hint_num_files_per_dir": 8,
"fsevents_latency": 0.05
}

View File

@ -154,9 +154,10 @@ class Config : private boost::noncopyable {
}
/// Get start time of config.
size_t getStartTime() const {
return start_time_;
}
static size_t getStartTime();
/// Set the start time if the config.
static void setStartTime(size_t st);
/**
* @brief Add a pack to the osquery schedule
@ -363,9 +364,6 @@ class Config : private boost::noncopyable {
/// Try if the configuration has started an auto-refresh thread.
bool started_thread_{false};
/// A UNIX timestamp recorded when the config started.
size_t start_time_{0};
private:
/// Hold a reference to the refresh runner to update the acceleration.
std::shared_ptr<ConfigRefreshRunner> refresh_runner_{nullptr};

View File

@ -167,6 +167,7 @@ class Initializer : private boost::noncopyable {
/// Initialize the osquery watcher, optionally spawn a worker.
void initWatcher() const;
/// This pauses the watchdog process until the watcher thread stops.
void waitForWatcher() const;
private:

View File

@ -89,6 +89,9 @@ DECLARE_string(pack_delimiter);
const std::string kExecutingQuery{"executing_query"};
const std::string kFailedQueries{"failed_queries"};
/// The time osquery was started.
std::atomic<size_t> kStartTime;
// The config may be accessed and updated asynchronously; use mutexes.
Mutex config_hash_mutex_;
Mutex config_valid_mutex_;
@ -259,7 +262,6 @@ Schedule::Schedule() {
Config::Config()
: schedule_(std::make_shared<Schedule>()),
valid_(false),
start_time_(getUnixTime()),
refresh_runner_(std::make_shared<ConfigRefreshRunner>()) {}
void Config::addPack(const std::string& name,
@ -291,6 +293,14 @@ void Config::addPack(const std::string& name,
}
}
size_t Config::getStartTime() {
return kStartTime;
}
void Config::setStartTime(size_t st) {
kStartTime = st;
}
void Config::removePack(const std::string& pack) {
RecursiveLock wlock(config_schedule_mutex_);
return schedule_->remove(pack);
@ -675,13 +685,14 @@ void Config::purge() {
}
void Config::reset() {
setStartTime(getUnixTime());
schedule_ = std::make_shared<Schedule>();
std::map<std::string, QueryPerformance>().swap(performance_);
std::map<std::string, FileCategories>().swap(files_);
std::map<std::string, std::string>().swap(hash_);
valid_ = false;
loaded_ = false;
start_time_ = getUnixTime();
// Also request each parse to reset state.
for (const auto& plugin : RegistryFactory::get().plugins("config_parser")) {

View File

@ -275,6 +275,8 @@ Initializer::Initializer(int& argc, char**& argv, ToolType tool)
binary_((tool == ToolType::DAEMON) ? "osqueryd" : "osqueryi") {
std::srand(static_cast<unsigned int>(
chrono_clock::now().time_since_epoch().count()));
// The config holds the initialization time for easy access.
Config::setStartTime(getUnixTime());
// Initialize registries and plugins
registryAndPluginInit();
@ -306,6 +308,7 @@ Initializer::Initializer(int& argc, char**& argv, ToolType tool)
{"Stderr log level threshold", false, false, true, false});
// osquery implements a custom help/usage output.
bool default_flags = true;
for (int i = 1; i < *argc_; i++) {
auto help = std::string((*argv_)[i]);
if ((help == "--help" || help == "-help" || help == "--h" ||
@ -314,6 +317,9 @@ Initializer::Initializer(int& argc, char**& argv, ToolType tool)
printUsage(binary_, tool_);
shutdown();
}
if (help.find("--flagfile") == 0) {
default_flags = false;
}
}
if (tool == ToolType::SHELL) {
@ -324,11 +330,12 @@ Initializer::Initializer(int& argc, char**& argv, ToolType tool)
FLAGS_disable_events = true;
}
bool default_flags = false;
if (FLAGS_flagfile.empty() && isReadable(kDefaultFlagfile)) {
if (default_flags && isReadable(kDefaultFlagfile)) {
// No flagfile was set (daemons and services always set a flagfile).
default_flags = true;
FLAGS_flagfile = kDefaultFlagfile;
} else {
// No flagfile was set, but no default flags exist.
default_flags = false;
}
// Set version string from CMake build
@ -459,6 +466,12 @@ void Initializer::initShell() const {
}
void Initializer::initWatcher() const {
// The watcher should not log into or use a persistent database.
FLAGS_disable_database = true;
FLAGS_disable_logging = true;
DatabasePlugin::setAllowOpen(true);
DatabasePlugin::initPlugin();
// The watcher takes a list of paths to autoload extensions from.
// The loadExtensions call will populate the watcher's list of extensions.
osquery::loadExtensions();
@ -590,7 +603,13 @@ void Initializer::start() const {
// Bind to an extensions socket and wait for registry additions.
// After starting the extension manager, osquery MUST shutdown using the
// internal 'shutdown' method.
osquery::startExtensionManager();
auto s = osquery::startExtensionManager();
if (!s.ok()) {
auto severity = (Watcher::get().hasManagedExtensions()) ? google::GLOG_ERROR
: google::GLOG_INFO;
google::LogMessage(__FILE__, __LINE__, severity).stream()
<< "Cannot start extension manager: " + s.getMessage();
}
// Then set the config plugin, which uses a single/active plugin.
initActivePlugin("config", FLAGS_config_plugin);
@ -600,7 +619,7 @@ void Initializer::start() const {
if (FLAGS_config_check) {
// The initiator requested an initialization and config check.
auto s = Config::get().load();
s = Config::get().load();
if (!s.ok()) {
std::cerr << "Error reading config: " << s.toString() << "\n";
}
@ -615,7 +634,7 @@ void Initializer::start() const {
}
// Load the osquery config using the default/active config plugin.
auto s = Config::get().load();
s = Config::get().load();
if (!s.ok()) {
auto message = "Error reading config: " + s.toString();
if (tool_ == ToolType::DAEMON) {

View File

@ -236,7 +236,7 @@ void WatcherRunner::start() {
}
size_t WatcherRunner::delayedTime() const {
return Config::get().getStartTime() + FLAGS_watchdog_delay;
return Config::getStartTime() + FLAGS_watchdog_delay;
}
bool WatcherRunner::watch(const PlatformProcess& child) const {

View File

@ -9,7 +9,6 @@
*/
#include <osquery/core.h>
#include <osquery/flags.h>
#include <osquery/logger.h>
#include <osquery/system.h>

View File

@ -308,15 +308,12 @@ void daemonEntry(int argc, char* argv[]) {
return;
}
if (!runner.isWorker()) {
runner.initDaemon();
}
// When a watchdog is used, the current daemon will fork/exec into a worker.
// In either case the watcher may start optionally loaded extensions.
if (runner.isWorker()) {
runner.initWorker(kWatcherWorkerName);
} else {
runner.initDaemon();
runner.initWatcher();
// The event only gets initialized in the entry point of the service. Child
@ -335,7 +332,7 @@ void daemonEntry(int argc, char* argv[]) {
// Start osquery work.
runner.start();
// Conditionally begin the distributed query service
// Conditionally begin the distributed query service.
auto s = osquery::startDistributed();
if (!s.ok()) {
VLOG(1) << "Not starting the distributed query service: " << s.toString();

View File

@ -210,7 +210,7 @@ QueryData genOsqueryInfo(QueryContext& context) {
(pingExtension(FLAGS_extensions_socket).ok()) ? "active" : "inactive";
r["build_platform"] = STR(OSQUERY_BUILD_PLATFORM);
r["build_distro"] = STR(OSQUERY_BUILD_DISTRO);
r["start_time"] = INTEGER(Config::get().getStartTime());
r["start_time"] = INTEGER(Config::getStartTime());
if (Initializer::isWorker()) {
r["watcher"] = INTEGER(PlatformProcess::getLauncherProcess()->pid());
} else {