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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2017-01-07 20:21:35 +00:00
|
|
|
#include <chrono>
|
2016-05-11 21:16:32 +00:00
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
2017-01-07 20:21:35 +00:00
|
|
|
#include <thread>
|
2016-05-11 21:16:32 +00:00
|
|
|
|
2017-01-07 20:21:35 +00:00
|
|
|
#include <boost/noncopyable.hpp>
|
|
|
|
#include <boost/optional.hpp>
|
2016-09-20 21:18:58 +00:00
|
|
|
|
|
|
|
#ifndef NOMINMAX
|
2016-05-11 21:16:32 +00:00
|
|
|
#define NOMINMAX
|
2016-09-20 21:18:58 +00:00
|
|
|
#endif
|
|
|
|
|
2017-01-07 20:21:35 +00:00
|
|
|
#ifdef WIN32
|
2016-05-11 21:16:32 +00:00
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#include <windows.h>
|
2016-09-12 16:46:52 +00:00
|
|
|
|
|
|
|
// Suppressing unexpected token following preprocessor directive warning
|
|
|
|
#pragma warning(push, 3)
|
|
|
|
#pragma warning(disable : 4067)
|
|
|
|
#include <sddl.h>
|
|
|
|
#pragma warning(pop)
|
2016-05-11 21:16:32 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <osquery/core.h>
|
2017-01-07 20:21:35 +00:00
|
|
|
#include <osquery/system.h>
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
|
|
|
/// Constant for an invalid process
|
2016-07-11 16:45:57 +00:00
|
|
|
const PlatformPidType kInvalidPid = (PlatformPidType)-1;
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Categories of process states adapted to be platform agnostic
|
|
|
|
*
|
|
|
|
* A process can have the following states. Unfortunately, because of operating
|
|
|
|
* system differences. A generic state change is not directly translatable on
|
|
|
|
* Windows. Therefore, PROCESS_STATE_CHANGE will only occur on POSIX systems.
|
|
|
|
*/
|
|
|
|
enum ProcessState {
|
|
|
|
PROCESS_ERROR = -1,
|
|
|
|
PROCESS_STILL_ALIVE = 0,
|
|
|
|
PROCESS_EXITED,
|
|
|
|
PROCESS_STATE_CHANGE
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Platform-agnostic process object.
|
|
|
|
*
|
|
|
|
* PlatformProcess is a specialized, platform-agnostic class that handles the
|
2016-05-14 02:47:45 +00:00
|
|
|
* process operation needs of osquery.
|
2016-05-11 21:16:32 +00:00
|
|
|
*/
|
|
|
|
class PlatformProcess : private boost::noncopyable {
|
|
|
|
public:
|
|
|
|
/// Default constructor marks the process as invalid
|
|
|
|
explicit PlatformProcess() : id_(kInvalidPid) {}
|
|
|
|
explicit PlatformProcess(PlatformPidType id);
|
|
|
|
|
2016-07-28 23:04:34 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
/*
|
|
|
|
* @brief Constructor that accepts a pid_t
|
2016-08-31 23:45:06 +00:00
|
|
|
*
|
2016-07-28 23:04:34 +00:00
|
|
|
* Allow for the creation of a PlatformProcess object from a pid_t. On
|
|
|
|
* Windows, PlatformPidType is not a pid_t because it cannot be assumed that
|
|
|
|
* the PID will point to the expected process. After a process dies, the PID
|
|
|
|
* can be immediately reused. Using HANDLEs (as what is done now) mitigates
|
|
|
|
* this issue.
|
|
|
|
*/
|
|
|
|
explicit PlatformProcess(pid_t pid);
|
|
|
|
#endif
|
|
|
|
|
2016-05-11 21:16:32 +00:00
|
|
|
PlatformProcess(const PlatformProcess& src) = delete;
|
2016-07-11 16:45:57 +00:00
|
|
|
PlatformProcess(PlatformProcess&& src) noexcept;
|
2016-07-21 19:33:14 +00:00
|
|
|
virtual ~PlatformProcess();
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
PlatformProcess& operator=(const PlatformProcess& process) = delete;
|
|
|
|
bool operator==(const PlatformProcess& process) const;
|
|
|
|
bool operator!=(const PlatformProcess& process) const;
|
|
|
|
|
2016-09-12 16:46:52 +00:00
|
|
|
/**
|
|
|
|
* @brief Returns the process's ID
|
|
|
|
*
|
|
|
|
* Returns the associated process' process ID (on POSIX, pid() and
|
|
|
|
* nativeHandle() do not differ).
|
|
|
|
*
|
|
|
|
* NOTE: In most situations, this should ideally not be used on Windows when
|
|
|
|
* dealing when tracking process lifetimes.
|
|
|
|
*/
|
2016-05-11 21:16:32 +00:00
|
|
|
int pid() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Returns the native "handle" object of the process.
|
|
|
|
*
|
|
|
|
* On Windows, this is in the of a HANDLE. For POSIX, this is just the pid_t
|
|
|
|
* of the process.
|
|
|
|
*/
|
2016-08-31 23:45:06 +00:00
|
|
|
PlatformPidType nativeHandle() const {
|
|
|
|
return id_;
|
|
|
|
}
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
/// Hard terminates the process
|
|
|
|
bool kill() const;
|
|
|
|
|
2017-01-15 09:25:59 +00:00
|
|
|
/**
|
|
|
|
* @brief Attempt to kill a process gracefully, usually a child process.
|
|
|
|
*/
|
|
|
|
bool killGracefully() const;
|
|
|
|
|
2017-01-13 02:09:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Wait or cleanup a process, usually a child process.
|
|
|
|
*
|
|
|
|
* This will wait for a process to cleanup. Use this after requesting a
|
|
|
|
* graceful shutdown.
|
|
|
|
*
|
|
|
|
* @return true if the process was cleaned, otherwise false.
|
|
|
|
*/
|
|
|
|
bool cleanup() const;
|
|
|
|
|
2016-05-11 21:16:32 +00:00
|
|
|
/// Returns whether the PlatformProcess object is valid
|
2016-08-31 23:45:06 +00:00
|
|
|
bool isValid() const {
|
|
|
|
return (id_ != kInvalidPid);
|
|
|
|
}
|
2016-05-11 21:16:32 +00:00
|
|
|
|
2016-07-21 19:33:14 +00:00
|
|
|
virtual ProcessState checkStatus(int& status) const;
|
|
|
|
|
2016-05-11 21:16:32 +00:00
|
|
|
/// Returns the current process
|
|
|
|
static std::shared_ptr<PlatformProcess> getCurrentProcess();
|
|
|
|
|
|
|
|
/// Returns the launcher process (only works for worker processes)
|
|
|
|
static std::shared_ptr<PlatformProcess> getLauncherProcess();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Creates a new worker process.
|
|
|
|
*
|
2016-05-14 02:47:45 +00:00
|
|
|
* Launches a worker process given a worker executable path, number of
|
2016-07-11 16:45:57 +00:00
|
|
|
* arguments, and an array of arguments. All double quotes within each entry
|
2016-05-14 02:47:45 +00:00
|
|
|
* in the array of arguments will be supplanted with a preceding blackslash.
|
2016-05-11 21:16:32 +00:00
|
|
|
*/
|
|
|
|
static std::shared_ptr<PlatformProcess> launchWorker(
|
2016-05-14 02:47:45 +00:00
|
|
|
const std::string& exec_path, int argc, char** argv);
|
2016-05-11 21:16:32 +00:00
|
|
|
|
|
|
|
/**
|
2016-07-28 23:04:34 +00:00
|
|
|
* @brief Creates a new extension process.
|
|
|
|
*
|
|
|
|
* Launches a new extension with various options. Any double quotes in the
|
|
|
|
* extension name will be stripped away.
|
|
|
|
*/
|
2016-05-11 21:16:32 +00:00
|
|
|
static std::shared_ptr<PlatformProcess> launchExtension(
|
|
|
|
const std::string& exec_path,
|
|
|
|
const std::string& extension,
|
|
|
|
const std::string& extensions_socket,
|
|
|
|
const std::string& extensions_timeout,
|
|
|
|
const std::string& extensions_interval,
|
2017-03-25 01:47:23 +00:00
|
|
|
bool verbose = false);
|
2016-05-11 21:16:32 +00:00
|
|
|
|
2016-09-12 16:46:52 +00:00
|
|
|
/**
|
|
|
|
* @brief Launches a new Python script
|
|
|
|
*
|
|
|
|
* This will launch a new Python process to run the specified script and
|
|
|
|
* script arguments
|
|
|
|
*/
|
|
|
|
static std::shared_ptr<PlatformProcess> launchPythonScript(
|
|
|
|
const std::string& args);
|
|
|
|
|
2016-05-11 21:16:32 +00:00
|
|
|
private:
|
2016-08-31 23:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief Stores the native handle denoting the process
|
|
|
|
*
|
|
|
|
* "Handle" of the process. On Windows, this will be a HANDLE. On POSIX
|
|
|
|
* systems, this will be a pid_t.
|
|
|
|
*/
|
|
|
|
PlatformPidType id_;
|
2016-05-11 21:16:32 +00:00
|
|
|
};
|
|
|
|
|
2016-07-28 23:04:34 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
/**
|
|
|
|
* @brief Handles the resource lifetime of a PSECURITY_DESCRIPTOR
|
|
|
|
*
|
|
|
|
* Class to handle the scope of a PSECURITY_DESCRIPTOR from
|
|
|
|
* GetSecurityInfo/GetNamedSecurityInfo class of functions (or any
|
|
|
|
* PSECURITY_DESCRIPTOR pointer where the buffer is allocated via LocalAlloc)
|
|
|
|
*/
|
|
|
|
class SecurityDescriptor {
|
2016-08-31 23:45:06 +00:00
|
|
|
public:
|
2016-07-28 23:04:34 +00:00
|
|
|
explicit SecurityDescriptor(PSECURITY_DESCRIPTOR sd) : sd_(sd) {}
|
|
|
|
|
2016-08-31 23:45:06 +00:00
|
|
|
SecurityDescriptor(SecurityDescriptor&& src) noexcept {
|
2016-07-28 23:04:34 +00:00
|
|
|
sd_ = src.sd_;
|
|
|
|
std::swap(sd_, src.sd_);
|
|
|
|
}
|
|
|
|
|
|
|
|
~SecurityDescriptor() {
|
|
|
|
if (sd_ != nullptr) {
|
|
|
|
::LocalFree(sd_);
|
|
|
|
sd_ = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-31 23:45:06 +00:00
|
|
|
private:
|
2016-07-28 23:04:34 +00:00
|
|
|
PSECURITY_DESCRIPTOR sd_{nullptr};
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2016-10-14 17:23:37 +00:00
|
|
|
/// Returns the current user's ID (UID on POSIX systems and RID for Windows)
|
|
|
|
int platformGetUid();
|
2016-09-12 16:46:52 +00:00
|
|
|
|
2017-01-07 20:21:35 +00:00
|
|
|
inline void sleepFor(size_t msec) {
|
|
|
|
std::chrono::milliseconds mduration(msec);
|
|
|
|
std::this_thread::sleep_for(mduration);
|
|
|
|
}
|
2016-05-11 21:16:32 +00:00
|
|
|
|
2016-07-21 19:33:14 +00:00
|
|
|
/// Set the enviroment variable name with value value.
|
2016-05-11 21:16:32 +00:00
|
|
|
bool setEnvVar(const std::string& name, const std::string& value);
|
|
|
|
|
2016-07-21 19:33:14 +00:00
|
|
|
/// Unsets the environment variable specified by name.
|
2016-05-11 21:16:32 +00:00
|
|
|
bool unsetEnvVar(const std::string& name);
|
|
|
|
|
|
|
|
/**
|
2016-07-21 19:33:14 +00:00
|
|
|
* @brief Returns the value of the specified environment variable name.
|
2016-05-11 21:16:32 +00:00
|
|
|
*
|
|
|
|
* If the environment variable does not exist, boost::none is returned.
|
|
|
|
*/
|
|
|
|
boost::optional<std::string> getEnvVar(const std::string& name);
|
|
|
|
|
2016-08-31 23:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief Returns a handle of the specified module path
|
|
|
|
*
|
|
|
|
* On POSIX, this invokes dlopen with RTLD_NOW and RTLD_LOCAL flags
|
|
|
|
*/
|
|
|
|
ModuleHandle platformModuleOpen(const std::string& path);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Returns a pointer of where the requested symbol exists
|
|
|
|
*/
|
|
|
|
void* platformModuleGetSymbol(ModuleHandle module, const std::string& symbol);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Returns a string of the last error
|
|
|
|
*
|
|
|
|
* On Windows, this returns the last error message which may not necessarily be
|
|
|
|
* from a module operation. It is suggested to call this immediately after a
|
|
|
|
* platformModule function for best accuracy.
|
|
|
|
*/
|
|
|
|
std::string platformModuleGetError();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Closes the library handle
|
|
|
|
*
|
|
|
|
* On Windows, this will also try to unload the library.
|
|
|
|
*/
|
|
|
|
bool platformModuleClose(ModuleHandle module);
|
|
|
|
|
2016-10-14 17:23:37 +00:00
|
|
|
/**
|
|
|
|
* @brief Checks to see if the launcher process is dead
|
|
|
|
*
|
|
|
|
* Note, this only works on worker processes.
|
|
|
|
*/
|
2016-05-11 21:16:32 +00:00
|
|
|
bool isLauncherProcessDead(PlatformProcess& launcher);
|
|
|
|
|
2016-07-21 19:33:14 +00:00
|
|
|
/// Sets the current process to run with background scheduling priority.
|
2016-05-11 21:16:32 +00:00
|
|
|
void setToBackgroundPriority();
|
2016-10-14 17:23:37 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Returns the current processes pid
|
|
|
|
*
|
|
|
|
* On Windows, returns the value of GetCurrentProcessId
|
|
|
|
* and on posix platforms returns getpid()
|
|
|
|
*/
|
|
|
|
int platformGetPid();
|
2016-12-03 07:24:08 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Returns the current thread id
|
|
|
|
*
|
|
|
|
* On Windows, returns the value of GetCurrentThreadId
|
|
|
|
* and on posix platforms returns gettid()
|
|
|
|
*/
|
|
|
|
int platformGetTid();
|
2016-05-11 21:16:32 +00:00
|
|
|
}
|