mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-08 02:18:53 +00:00
Merge pull request #1605 from theopolis/linux_system_info
[#1546] Add computer_name to system_info and extend to Linux
This commit is contained in:
commit
501c20c284
@ -78,7 +78,6 @@ endif()
|
||||
# Construct a set of all object files, starting with third-party and all
|
||||
# of the osquery core objects (sources from ADD_CORE_LIBRARY macros).
|
||||
set(OSQUERY_OBJECTS $<TARGET_OBJECTS:osquery_sqlite>)
|
||||
add_compile_options(-Werror)
|
||||
|
||||
# Add subdirectories
|
||||
add_subdirectory(config)
|
||||
|
@ -55,9 +55,14 @@ FLAG(string,
|
||||
"Field used to identify the host running osquery (hostname, uuid)");
|
||||
|
||||
std::string getHostname() {
|
||||
char hostname[256] = {0}; // Linux max should be 64.
|
||||
gethostname(hostname, sizeof(hostname) - 1);
|
||||
static long max_hostname = sysconf(_SC_HOST_NAME_MAX);
|
||||
long size = (max_hostname > 255) ? max_hostname + 1 : 256;
|
||||
char* hostname = (char*)malloc(size);
|
||||
memset((void*)hostname, 0, size);
|
||||
gethostname(hostname, size - 1);
|
||||
std::string hostname_string = std::string(hostname);
|
||||
free(hostname);
|
||||
|
||||
boost::algorithm::trim(hostname_string);
|
||||
return hostname_string;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <osquery/flags.h>
|
||||
#include <osquery/logger.h>
|
||||
|
||||
#include "osquery/database/db_handle.h"
|
||||
#include "osquery/sql/sqlite_util.h"
|
||||
|
||||
DEFINE_string(query, "", "query to execute");
|
||||
@ -40,6 +41,8 @@ int main(int argc, char* argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
osquery::DBHandle::setAllowOpen(true);
|
||||
osquery::FLAGS_database_path = "/dev/null";
|
||||
osquery::Registry::setUp();
|
||||
osquery::FLAGS_disable_events = true;
|
||||
osquery::FLAGS_registry_exceptions = true;
|
||||
|
@ -45,23 +45,23 @@ std::map<int, std::vector<FeatureDef_t> > kCPUFeatures = {
|
||||
}},
|
||||
};
|
||||
|
||||
void cpuid(unsigned int eax, unsigned int ecx, int regs[4]) {
|
||||
static inline void cpuid(unsigned int eax, unsigned int ecx, int regs[4]) {
|
||||
asm volatile("cpuid"
|
||||
: "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
|
||||
: "a"(eax), "c"(ecx));
|
||||
}
|
||||
|
||||
void registerToString(int reg, std::stringstream& stream) {
|
||||
static inline void registerToString(int reg, std::stringstream& stream) {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
stream << ((char*)®)[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool isBitSet(size_t bit, unsigned int reg) {
|
||||
static inline bool isBitSet(size_t bit, unsigned int reg) {
|
||||
return ((reg & (1 << bit)) != 0);
|
||||
}
|
||||
|
||||
Status genVendorString(QueryData& results) {
|
||||
inline Status genStrings(QueryData& results) {
|
||||
int regs[4] = {-1};
|
||||
|
||||
cpuid(0, 0, regs);
|
||||
@ -73,7 +73,7 @@ Status genVendorString(QueryData& results) {
|
||||
std::stringstream vendor_string;
|
||||
registerToString(regs[1], vendor_string);
|
||||
registerToString(regs[3], vendor_string);
|
||||
registerToString(regs[2], vendor_string);
|
||||
registerToString(regs[2], vendor_string);
|
||||
|
||||
Row r;
|
||||
r["feature"] = "vendor";
|
||||
@ -83,10 +83,59 @@ Status genVendorString(QueryData& results) {
|
||||
r["input_eax"] = "0";
|
||||
results.push_back(r);
|
||||
|
||||
// The CPU canonicalized name can also be accessed via cpuid accesses.
|
||||
// Subsequent accesses allow a 32-character CPU name.
|
||||
std::stringstream product_name;
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
cpuid(0x80000002 + i, 0, regs);
|
||||
registerToString(regs[0], product_name);
|
||||
registerToString(regs[1], product_name);
|
||||
registerToString(regs[2], product_name);
|
||||
registerToString(regs[3], product_name);
|
||||
}
|
||||
|
||||
r["feature"] = "product_name";
|
||||
r["value"] = product_name.str();
|
||||
r["output_register"] = "eax,ebx,ecx,edx";
|
||||
r["output_bit"] = "0";
|
||||
r["input_eax"] = "0x80000002";
|
||||
results.push_back(r);
|
||||
|
||||
// Do the same to grab the optional hypervisor ID.
|
||||
cpuid(0x40000000, 0, regs);
|
||||
if (regs[0] && 0xFF000000 != 0) {
|
||||
std::stringstream hypervisor_string;
|
||||
registerToString(regs[1], hypervisor_string);
|
||||
registerToString(regs[2], hypervisor_string);
|
||||
registerToString(regs[3], hypervisor_string);
|
||||
|
||||
r["feature"] = "hypervisor_id";
|
||||
r["value"] = hypervisor_string.str();
|
||||
r["output_register"] = "ebx,ecx,edx";
|
||||
r["output_bit"] = "0";
|
||||
r["input_eax"] = "0x40000000";
|
||||
results.push_back(r);
|
||||
}
|
||||
|
||||
// Finally, check the processor serial number.
|
||||
std::stringstream serial;
|
||||
cpuid(1, 0, regs);
|
||||
serial << std::hex << std::setw(8) << std::setfill('0') << (int)regs[0];
|
||||
cpuid(3, 0, regs);
|
||||
serial << std::hex << std::setw(8) << std::setfill('0') << (int)regs[0];
|
||||
serial << std::hex << std::setw(8) << std::setfill('0') << (int)regs[3];
|
||||
|
||||
r["feature"] = "serial";
|
||||
r["value"] = serial.str();
|
||||
r["output_register"] = "eax,ebx,ecx,edx";
|
||||
r["output_bit"] = "0";
|
||||
r["input_eax"] = "1,3";
|
||||
results.push_back(r);
|
||||
|
||||
return Status(0, "OK");
|
||||
}
|
||||
|
||||
void genFamily(QueryData& results) {
|
||||
inline void genFamily(QueryData& results) {
|
||||
int regs[4] = {-1};
|
||||
|
||||
cpuid(1, 0, regs);
|
||||
@ -108,7 +157,7 @@ void genFamily(QueryData& results) {
|
||||
QueryData genCPUID(QueryContext& context) {
|
||||
QueryData results;
|
||||
|
||||
if (!genVendorString(results).ok()) {
|
||||
if (!genStrings(results).ok()) {
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,11 @@
|
||||
*/
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include <osquery/database.h>
|
||||
#include <osquery/tables.h>
|
||||
#include <osquery/logger.h>
|
||||
|
||||
#include "osquery/core/conversions.h"
|
||||
#include "osquery/tables/system/sysctl_utils.h"
|
||||
@ -26,10 +26,10 @@ namespace tables {
|
||||
const std::string kMachCpuBrandStringKey = "machdep.cpu.brand_string";
|
||||
const std::string kHardwareModelNameKey = "hw.model";
|
||||
|
||||
Status getCpuSerial(std::string &cpu_serial) {
|
||||
Status getHardwareSerial(std::string &serial) {
|
||||
static std::string serial_cache;
|
||||
if (!serial_cache.empty()) {
|
||||
cpu_serial = serial_cache;
|
||||
serial = serial_cache;
|
||||
return Status(0, "OK");
|
||||
}
|
||||
|
||||
@ -61,12 +61,8 @@ Status getCpuSerial(std::string &cpu_serial) {
|
||||
return Status(1, "Could not read serial number property");
|
||||
}
|
||||
|
||||
cpu_serial = serial_cache = stringFromCFString(serialNumber);
|
||||
serial = serial_cache = stringFromCFString(serialNumber);
|
||||
CFRelease(serialNumber);
|
||||
if (cpu_serial.empty()) {
|
||||
return Status(1, "cpu_serial was empty");
|
||||
}
|
||||
|
||||
return Status(0, "OK");
|
||||
}
|
||||
|
||||
@ -77,7 +73,6 @@ void genHostInfo(Row &r) {
|
||||
|
||||
if (host_info(host, HOST_BASIC_INFO, (host_info_t)&host_data, &count) !=
|
||||
KERN_SUCCESS) {
|
||||
VLOG(1) << "Error retrieving host info";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -97,22 +92,21 @@ void genHostInfo(Row &r) {
|
||||
QueryData genSystemInfo(QueryContext &context) {
|
||||
QueryData results;
|
||||
Row r;
|
||||
r["hostname"] = TEXT(osquery::getHostname());
|
||||
r["hostname"] = osquery::getHostname();
|
||||
|
||||
// OS X also defines a friendly ComputerName.
|
||||
auto cn = SCDynamicStoreCopyComputerName(nullptr, nullptr);
|
||||
if (cn != nullptr) {
|
||||
r["computer_name"] = stringFromCFString(cn);
|
||||
CFRelease(cn);
|
||||
} else {
|
||||
r["computer_name"] = r["hostname"];
|
||||
}
|
||||
|
||||
std::string uuid;
|
||||
auto status = osquery::getHostUUID(uuid);
|
||||
if (!status.ok()) {
|
||||
uuid = "";
|
||||
}
|
||||
r["uuid"] = TEXT(uuid);
|
||||
|
||||
std::string cpu_serial;
|
||||
status = getCpuSerial(cpu_serial);
|
||||
if (!status.ok()) {
|
||||
cpu_serial = "";
|
||||
}
|
||||
r["cpu_serial"] = TEXT(cpu_serial);
|
||||
|
||||
r["uuid"] = (osquery::getHostUUID(uuid)) ? uuid : "";
|
||||
std::string serial;
|
||||
r["hardware_serial"] = (getHardwareSerial(serial)) ? serial : "";
|
||||
genHostInfo(r);
|
||||
|
||||
QueryData sysctl_results;
|
||||
|
77
osquery/tables/system/linux/system_info.cpp
Normal file
77
osquery/tables/system/linux/system_info.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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 <stdio.h>
|
||||
|
||||
#include <osquery/filesystem.h>
|
||||
#include <osquery/tables.h>
|
||||
#include <osquery/sql.h>
|
||||
|
||||
namespace osquery {
|
||||
namespace tables {
|
||||
|
||||
QueryData genSystemInfo(QueryContext &context) {
|
||||
Row r;
|
||||
r["hostname"] = osquery::getHostname();
|
||||
r["computer_name"] = r["hostname"];
|
||||
|
||||
std::string uuid;
|
||||
r["uuid"] = (osquery::getHostUUID(uuid)) ? uuid : "";
|
||||
|
||||
auto qd = SQL::selectAllFrom("cpuid");
|
||||
for (const auto& row : qd) {
|
||||
if (row.at("feature") == "product_name") {
|
||||
r["cpu_brand"] = row.at("value");
|
||||
}
|
||||
}
|
||||
|
||||
// Can parse /proc/cpuinfo or /proc/meminfo for this data.
|
||||
static long cores = sysconf(_SC_NPROCESSORS_CONF);
|
||||
if (cores > 0) {
|
||||
r["cpu_logical_cores"] = INTEGER(cores);
|
||||
r["cpu_physical_cores"] = INTEGER(cores);
|
||||
} else {
|
||||
r["cpu_logical_cores"] = "-1";
|
||||
r["cpu_physical_cores"] = "-1";
|
||||
}
|
||||
|
||||
static long pages = sysconf(_SC_PHYS_PAGES);
|
||||
static long pagesize = sysconf(_SC_PAGESIZE);
|
||||
|
||||
if (pages > 0 && pagesize > 0) {
|
||||
r["physical_memory"] = BIGINT((long long)pages * (long long)pagesize);
|
||||
} else {
|
||||
r["physical_memory"] = "-1";
|
||||
}
|
||||
|
||||
r["cpu_type"] = "0";
|
||||
r["cpu_subtype"] = "0";
|
||||
// Read the types from CPU info within proc.
|
||||
std::string content;
|
||||
if (readFile("/proc/cpuinfo", content)) {
|
||||
for (const auto& line : osquery::split(content, "\n")) {
|
||||
// Iterate each line and look for labels (there is also a model type).
|
||||
if (line.find("cpu family") == 0 || line.find("model\t") == 0) {
|
||||
auto details = osquery::split(line, ":");
|
||||
if (details.size() == 2) {
|
||||
// Not the most elegant but prevents us from splitting each line.
|
||||
r[(line[0] == 'c') ? "cpu_type" : "cpu_subtype"] = details[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Will require parsing DMI/SMBIOS data.
|
||||
r["hardware_model"] = "";
|
||||
r["hardware_serial"] = "";
|
||||
return {r};
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ description("System information for identification.")
|
||||
schema([
|
||||
Column("hostname", TEXT, "Network hostname including domain"),
|
||||
Column("uuid", TEXT, "Unique ID provided by the system"),
|
||||
Column("cpu_serial", TEXT, "System serial number frequently used for asset tracking"),
|
||||
Column("cpu_type", TEXT, "CPU type"),
|
||||
Column("cpu_subtype", TEXT, "CPU subtype"),
|
||||
Column("cpu_brand", TEXT, "CPU brand string"),
|
||||
@ -11,5 +10,8 @@ schema([
|
||||
Column("cpu_logical_cores", INTEGER, "Max number of CPU logical cores"),
|
||||
Column("physical_memory", BIGINT, "Total physical memory in bytes"),
|
||||
Column("hardware_model", TEXT, "Hardware model string"),
|
||||
Column("hardware_serial", TEXT,
|
||||
"System serial number frequently used for asset tracking"),
|
||||
Column("computer_name", TEXT, "Friendly computer name (optional)"),
|
||||
])
|
||||
implementation("system/system_info@genSystemInfo")
|
@ -140,7 +140,6 @@ def profile_cmd(cmd, proc=None, shell=False, timeout=0, count=1):
|
||||
shell=shell,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
p = psutil.Process(pid=proc.pid)
|
||||
|
||||
delay = 0
|
||||
@ -170,6 +169,8 @@ def profile_cmd(cmd, proc=None, shell=False, timeout=0, count=1):
|
||||
else:
|
||||
avg_utilization = sum(utilization) / len(utilization)
|
||||
|
||||
if len(stats.keys()) == 0:
|
||||
raise Exception("No stats recorded, perhaps binary returns -1?")
|
||||
return {
|
||||
"utilization": avg_utilization,
|
||||
"duration": duration,
|
||||
|
Loading…
Reference in New Issue
Block a user