mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-08 02:18:53 +00:00
62336ee8bb
When a thread different from the main requests a shutdown through Initializer::requestShutdown, it should not call waitForShutdown; there's no reason to wait, moreover the function doesn't only wait, but also actually stops other components and then finally calls exit(). Since the main thread is already inside the waitForShutdown call waiting on Dispatcher::joinServices or inside the shutdown() callable on Windows, having a secondary thread do the same work potentially at the same time is wrong. Moreover calling exit() from a secondary thread is most of the time incorrect. The waitForShutdown function has been renamed to waitThenShutdown to better represent what it's actually doing.
189 lines
5.5 KiB
C++
189 lines
5.5 KiB
C++
/**
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed in accordance with the terms specified in
|
|
* the LICENSE file found in the root directory of this source tree.
|
|
*/
|
|
|
|
#ifdef WIN32
|
|
#include <io.h>
|
|
#endif
|
|
|
|
#include <iostream>
|
|
|
|
#include <boost/algorithm/string/predicate.hpp>
|
|
|
|
#include <osquery/core.h>
|
|
#include <osquery/core/watcher.h>
|
|
#include <osquery/database.h>
|
|
#include <osquery/devtools/devtools.h>
|
|
#include <osquery/dispatcher/distributed_runner.h>
|
|
#include <osquery/dispatcher/scheduler.h>
|
|
#include <osquery/extensions.h>
|
|
#include <osquery/filesystem/fileops.h>
|
|
#include <osquery/flags.h>
|
|
#include <osquery/logger.h>
|
|
#include <osquery/main/main.h>
|
|
#include <osquery/process/process.h>
|
|
#include <osquery/registry_factory.h>
|
|
#include <osquery/sql/sqlite_util.h>
|
|
#include <osquery/system.h>
|
|
|
|
#include <osquery/experimental/tracing/syscalls_tracing.h>
|
|
|
|
namespace fs = boost::filesystem;
|
|
|
|
namespace osquery {
|
|
|
|
SHELL_FLAG(int32,
|
|
profile,
|
|
0,
|
|
"Enable profile mode when non-0, set number of iterations");
|
|
|
|
HIDDEN_FLAG(int32,
|
|
profile_delay,
|
|
0,
|
|
"Sleep a number of seconds before and after the profiling");
|
|
|
|
CLI_FLAG(bool, install, false, "Install osqueryd as a service");
|
|
|
|
CLI_FLAG(bool, uninstall, false, "Uninstall osqueryd as a service");
|
|
|
|
DECLARE_bool(disable_caching);
|
|
|
|
const std::string kWatcherWorkerName{"osqueryd: worker"};
|
|
|
|
int profile(int argc, char* argv[]) {
|
|
std::string query;
|
|
if (!osquery::platformIsatty(stdin)) {
|
|
std::getline(std::cin, query);
|
|
} else if (argc < 2) {
|
|
// No query input provided via stdin or as a positional argument.
|
|
std::cerr << "No query provided via stdin or args to profile..."
|
|
<< std::endl;
|
|
return 2;
|
|
} else {
|
|
query = std::string(argv[1]);
|
|
}
|
|
|
|
if (osquery::FLAGS_profile_delay > 0) {
|
|
osquery::sleepFor(osquery::FLAGS_profile_delay * 1000);
|
|
}
|
|
|
|
// Perform some duplication from Initializer with respect to database setup.
|
|
osquery::DatabasePlugin::setAllowOpen(true);
|
|
osquery::RegistryFactory::get().setActive("database", "ephemeral");
|
|
|
|
auto dbc = osquery::SQLiteDBManager::get();
|
|
for (size_t i = 0; i < static_cast<size_t>(osquery::FLAGS_profile); ++i) {
|
|
osquery::QueryData results;
|
|
auto status = osquery::queryInternal(query, results, dbc);
|
|
dbc->clearAffectedTables();
|
|
if (!status) {
|
|
std::cerr << "Query failed (" << status.getCode()
|
|
<< "): " << status.what() << std::endl;
|
|
return status.getCode();
|
|
}
|
|
}
|
|
|
|
if (osquery::FLAGS_profile_delay > 0) {
|
|
osquery::sleepFor(osquery::FLAGS_profile_delay * 1000);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int startDaemon(Initializer& runner) {
|
|
runner.start();
|
|
|
|
// Conditionally begin the distributed query service
|
|
auto s = startDistributed();
|
|
if (!s.ok()) {
|
|
VLOG(1) << "Not starting the distributed query service: " << s.toString();
|
|
}
|
|
|
|
// Begin the schedule runloop.
|
|
startScheduler();
|
|
|
|
osquery::events::init_syscall_tracing();
|
|
|
|
// Finally wait for a signal / interrupt to shutdown.
|
|
runner.waitThenShutdown();
|
|
return 0;
|
|
}
|
|
|
|
int startShell(osquery::Initializer& runner, int argc, char* argv[]) {
|
|
// Check for shell-specific switches and positional arguments.
|
|
if (argc > 1 || !osquery::platformIsatty(stdin) ||
|
|
!osquery::FLAGS_A.empty() || !osquery::FLAGS_pack.empty() ||
|
|
osquery::FLAGS_L || osquery::FLAGS_profile > 0) {
|
|
// A query was set as a positional argument, via stdin, or profiling is on.
|
|
osquery::FLAGS_disable_events = true;
|
|
osquery::FLAGS_disable_caching = true;
|
|
// The shell may have loaded table extensions, if not, disable the manager.
|
|
if (!osquery::Watcher::get().hasManagedExtensions() &&
|
|
Flag::isDefault("disable_extensions")) {
|
|
osquery::FLAGS_disable_extensions = true;
|
|
}
|
|
}
|
|
|
|
int retcode = 0;
|
|
if (osquery::FLAGS_profile <= 0) {
|
|
runner.start();
|
|
|
|
// Virtual tables will be attached to the shell's in-memory SQLite DB.
|
|
retcode = osquery::launchIntoShell(argc, argv);
|
|
} else {
|
|
retcode = profile(argc, argv);
|
|
}
|
|
// Finally shutdown.
|
|
runner.requestShutdown();
|
|
return retcode;
|
|
}
|
|
|
|
int startOsquery(int argc, char* argv[], std::function<void()> shutdown) {
|
|
// Parse/apply flags, start registry, load logger/config plugins.
|
|
osquery::Initializer runner(argc, argv, osquery::ToolType::SHELL_DAEMON);
|
|
|
|
// Options for installing or uninstalling the osqueryd as a service
|
|
if (FLAGS_install && FLAGS_uninstall) {
|
|
LOG(ERROR) << "osqueryd service install and uninstall can not be "
|
|
"requested together";
|
|
return 1;
|
|
}
|
|
|
|
if (FLAGS_install) {
|
|
auto binPath = fs::system_complete(fs::path(argv[0]));
|
|
// "Wrap" the binPath in the event it contains spaces
|
|
if (installService("\"" + binPath.string() + "\"")) {
|
|
LOG(INFO) << "osqueryd service was installed successfully.";
|
|
return 0;
|
|
} else {
|
|
LOG(ERROR) << "Unable to install the osqueryd service";
|
|
return 1;
|
|
}
|
|
} else if (FLAGS_uninstall) {
|
|
if (uninstallService()) {
|
|
LOG(INFO) << "osqueryd service was uninstalled successfully.";
|
|
return 0;
|
|
} else {
|
|
LOG(ERROR) << "Unable to uninstall the osqueryd service";
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
runner.installShutdown(shutdown);
|
|
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.
|
|
runner.initWorkerWatcher(kWatcherWorkerName);
|
|
|
|
if (runner.isDaemon()) {
|
|
return startDaemon(runner);
|
|
}
|
|
return startShell(runner, argc, argv);
|
|
}
|
|
} // namespace osquery
|