mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-07 18:08:53 +00:00
Merge pull request #383 from theopolis/fix_rpm_packages
[Fix #367] Check RPMTAG class before cast
This commit is contained in:
commit
bc05f5de78
@ -13,6 +13,9 @@ else()
|
||||
endif()
|
||||
|
||||
set(OS_COMPILE_FLAGS "-std=c++11")
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(OS_COMPILE_FLAGS "${OS_COMPILE_FLAGS} -g")
|
||||
endif()
|
||||
set(OS_WHOLELINK_PRE "-Wl,-whole-archive")
|
||||
set(OS_WHOLELINK_POST "-Wl,-no-whole-archive")
|
||||
endif()
|
||||
|
3
Makefile
3
Makefile
@ -11,7 +11,8 @@ else
|
||||
endif
|
||||
|
||||
all: .setup
|
||||
cd build/$(BUILD_DIR) && cmake ../.. && make --no-print-directory $(MAKEFLAGS)
|
||||
cd build/$(BUILD_DIR) && cmake -DCMAKE_BUILD_TYPE= ../.. && \
|
||||
make --no-print-directory $(MAKEFLAGS)
|
||||
|
||||
debug: .setup
|
||||
cd build/$(BUILD_DIR) && cmake -DCMAKE_BUILD_TYPE=Debug ../../ && \
|
||||
|
@ -12,9 +12,9 @@
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include "osquery/status.h"
|
||||
#include "osquery/database.h"
|
||||
#include "osquery/registry.h"
|
||||
#include "osquery/status.h"
|
||||
|
||||
namespace osquery {
|
||||
|
||||
|
@ -4361,10 +4361,6 @@ int launchIntoShell(int argc, char **argv) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "%s: Error: unknown option: %s\n", Argv0, z);
|
||||
fprintf(stderr, "Use -help for a list of options.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4431,7 +4427,10 @@ int launchIntoShell(int argc, char **argv) {
|
||||
sqlite3_close(data.db);
|
||||
}
|
||||
sqlite3_free(data.zFreeOnClose);
|
||||
free(data.prettyPrint);
|
||||
|
||||
if (data.prettyPrint != nullptr) {
|
||||
delete data.prettyPrint;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,16 @@
|
||||
#include "osquery/core.h"
|
||||
#include "osquery/core/conversions.h"
|
||||
#include "osquery/events.h"
|
||||
#include "osquery/flags.h"
|
||||
#include "osquery/dispatcher.h"
|
||||
|
||||
namespace osquery {
|
||||
|
||||
DEFINE_osquery_flag(bool,
|
||||
event_pubsub,
|
||||
true,
|
||||
"Use (enable) the osquery eventing pub/sub.")
|
||||
|
||||
const std::vector<size_t> kEventTimeLists = {
|
||||
1 * 60, // 1 minute
|
||||
1 * 60 * 60, // 1 hour
|
||||
@ -375,6 +381,10 @@ Status EventFactory::deregisterEventPublishers() {
|
||||
namespace osquery {
|
||||
namespace registries {
|
||||
void faucet(EventPublishers ets, EventSubscribers ems) {
|
||||
if (!FLAGS_event_pubsub) {
|
||||
// Invocation disabled eventing.
|
||||
return;
|
||||
}
|
||||
auto& ef = osquery::EventFactory::getInstance();
|
||||
for (const auto& event_pub : ets) {
|
||||
ef.registerEventPublisher(event_pub.second);
|
||||
|
@ -5,9 +5,7 @@ schema([
|
||||
Column(name="release", type="std::string"),
|
||||
Column(name="source", type="std::string"),
|
||||
Column(name="size", type="std::string"),
|
||||
Column(name="dsaheader", type="std::string"),
|
||||
Column(name="rsaheader", type="std::string"),
|
||||
Column(name="sha1header", type="std::string"),
|
||||
Column(name="sha1", type="std::string"),
|
||||
Column(name="arch", type="std::string"),
|
||||
])
|
||||
implementation("system/rpm_packages@genRpms")
|
||||
|
@ -12,56 +12,84 @@
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "osquery/logger.h"
|
||||
#include "osquery/database.h"
|
||||
|
||||
namespace osquery {
|
||||
namespace tables {
|
||||
|
||||
/**
|
||||
* @brief Return a string representation of the RPM tag type.
|
||||
*
|
||||
* @param header A librpm header.
|
||||
* @param tag A librpm rpmTag_t name.
|
||||
* @param td A librpm rpmtd.
|
||||
*
|
||||
* Given a librpm iterator header and a requested tag name:
|
||||
* 1. Determine the type of the tag (the class of value).
|
||||
* 2. Request a const pointer or cast of numerate to that class.
|
||||
* 3. Lexical-cast the value for SQL.
|
||||
*
|
||||
* @return The string representation of the tag type.
|
||||
*/
|
||||
std::string getRpmAttribute(const Header& header, rpmTag tag, const rpmtd& td) {
|
||||
std::string result;
|
||||
|
||||
if (headerGet(header, tag, td, HEADERGET_DEFAULT) == 0) {
|
||||
// Intentional check for a 0 = failure.
|
||||
VLOG(3) << "Could not get RPM header flag.";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (rpmTagGetClass(tag) == RPM_NUMERIC_CLASS) {
|
||||
long long int attr = rpmtdGetNumber(td);
|
||||
result = boost::lexical_cast<std::string>(attr);
|
||||
} else if (rpmTagGetClass(tag) == RPM_STRING_CLASS) {
|
||||
const char* attr = rpmtdGetString(td);
|
||||
if (attr != nullptr) {
|
||||
result = std::string(attr);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QueryData genRpms() {
|
||||
QueryData results;
|
||||
|
||||
// The following implementation uses http://rpm.org/api/4.11.1/
|
||||
Header header;
|
||||
rpmdbMatchIterator match_iterator;
|
||||
rpmReadConfigFiles(NULL, NULL);
|
||||
|
||||
rpmInitCrypto();
|
||||
if (rpmReadConfigFiles(nullptr, nullptr) != 0) {
|
||||
LOG(ERROR) << "Cannot read RPM configuration files.";
|
||||
return results;
|
||||
}
|
||||
|
||||
rpmts ts = rpmtsCreate();
|
||||
match_iterator = rpmtsInitIterator(ts, RPMTAG_NAME, NULL, 0);
|
||||
while ((header = rpmdbNextIterator(match_iterator)) != NULL) {
|
||||
Row r;
|
||||
rpmtd td = rpmtdNew();
|
||||
r["name"] = getRpmAttribute(header, RPMTAG_NAME, td);
|
||||
r["version"] = getRpmAttribute(header, RPMTAG_VERSION, td);
|
||||
r["release"] = getRpmAttribute(header, RPMTAG_RELEASE, td);
|
||||
r["source"] = getRpmAttribute(header, RPMTAG_SOURCERPM, td);
|
||||
r["size"] = getRpmAttribute(header, RPMTAG_SIZE, td);
|
||||
r["sha1"] = getRpmAttribute(header, RPMTAG_SHA1HEADER, td);
|
||||
r["arch"] = getRpmAttribute(header, RPMTAG_ARCH, td);
|
||||
|
||||
headerGet(header, RPMTAG_NAME, td, HEADERGET_DEFAULT);
|
||||
r["name"] = std::string(rpmtdGetString(td));
|
||||
|
||||
headerGet(header, RPMTAG_VERSION, td, HEADERGET_DEFAULT);
|
||||
r["version"] = std::string(rpmtdGetString(td));
|
||||
|
||||
headerGet(header, RPMTAG_RELEASE, td, HEADERGET_DEFAULT);
|
||||
r["release"] = std::string(rpmtdGetString(td));
|
||||
|
||||
headerGet(header, RPMTAG_SOURCERPM, td, HEADERGET_DEFAULT);
|
||||
r["source"] = std::string(rpmtdGetString(td));
|
||||
|
||||
headerGet(header, RPMTAG_SIZE, td, HEADERGET_DEFAULT);
|
||||
r["size"] = std::string(rpmtdGetString(td));
|
||||
|
||||
headerGet(header, RPMTAG_DSAHEADER, td, HEADERGET_DEFAULT);
|
||||
r["dsaheader"] = std::string(rpmtdGetString(td));
|
||||
|
||||
headerGet(header, RPMTAG_RSAHEADER, td, HEADERGET_DEFAULT);
|
||||
r["rsaheader"] = std::string(rpmtdGetString(td));
|
||||
|
||||
headerGet(header, RPMTAG_SHA1HEADER, td, HEADERGET_DEFAULT);
|
||||
r["sha1header"] = std::string(rpmtdGetString(td));
|
||||
|
||||
headerGet(header, RPMTAG_ARCH, td, HEADERGET_DEFAULT);
|
||||
r["arch"] = std::string(rpmtdGetString(td));
|
||||
|
||||
rpmtdFree(td);
|
||||
results.push_back(r);
|
||||
}
|
||||
|
||||
rpmdbFreeIterator(match_iterator);
|
||||
rpmtsFree(ts);
|
||||
|
||||
rpmFreeCrypto();
|
||||
rpmFreeRpmrc();
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,13 @@ from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
try:
|
||||
import argparse
|
||||
except ImportError:
|
||||
print ("Cannot import argparse.")
|
||||
print ("Try: sudo yum install python-argparse")
|
||||
exit(1)
|
||||
|
||||
import json
|
||||
import os
|
||||
import psutil
|
||||
@ -54,7 +60,9 @@ def queries_from_tables(path, restrict):
|
||||
tables.append("%s.%s" % (spec_platform, table_name))
|
||||
|
||||
tables = [t for t in tables if t not in restrict_tables]
|
||||
queries = {t: "SELECT * FROM %s;" % t.split(".", 1)[1] for t in tables}
|
||||
queries = {}
|
||||
for table in tables:
|
||||
queries[table] = "SELECT * FROM %s;" % table.split(".", 1)[1]
|
||||
return queries
|
||||
|
||||
def get_stats(p, interval=1):
|
||||
@ -68,6 +76,45 @@ def get_stats(p, interval=1):
|
||||
"memory": p.memory_info_ex(),
|
||||
}
|
||||
|
||||
def check_leaks(shell, query, supp_file=None):
|
||||
"""Run valgrind using the shell and a query, parse leak reports."""
|
||||
start_time = time.time()
|
||||
suppressions = "" if supp_file is None else "--suppressions=%s" % supp_file
|
||||
cmd = "valgrind --tool=memcheck %s %s --query=\"%s\"" % (
|
||||
suppressions, shell, query)
|
||||
proc = subprocess.Popen(cmd,
|
||||
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = proc.communicate()
|
||||
summary = {
|
||||
"definitely": None,
|
||||
"indirectly": None,
|
||||
"possibly": None,
|
||||
}
|
||||
for line in stderr.split("\n"):
|
||||
for key in summary:
|
||||
if line.find(key) >= 0:
|
||||
summary[key] = line.split(":")[1].strip()
|
||||
return summary
|
||||
|
||||
def profile_leaks(shell, queries, supp_file=None):
|
||||
report = {}
|
||||
for name, query in queries.iteritems():
|
||||
print ("Analyzing leaks in query: %s" % query)
|
||||
summary = check_leaks(shell, query, supp_file)
|
||||
display = []
|
||||
for key in summary:
|
||||
output = summary[key]
|
||||
if output is not None and output[0] != "0":
|
||||
# Add some fun colored output if leaking.
|
||||
if key == "definitely":
|
||||
output = red(output)
|
||||
if key == "indirectly":
|
||||
output = yellow(output)
|
||||
display.append("%s: %s" % (key, output))
|
||||
print (" %s" % "; ".join(display))
|
||||
report[name] = summary
|
||||
return report
|
||||
|
||||
def run_query(shell, query, timeout=0, count=1):
|
||||
"""Execute the osquery run testing wrapper with a setup/teardown delay."""
|
||||
start_time = time.time()
|
||||
@ -174,6 +221,10 @@ if __name__ == "__main__":
|
||||
help="Number of times to run each query.")
|
||||
parser.add_argument("--rounds", default=1, type=int,
|
||||
help="Run the profile for multiple rounds and use the average.")
|
||||
parser.add_argument("--leaks", default=False, action="store_true",
|
||||
help="Check for memory leaks instead of performance.")
|
||||
parser.add_argument("--suppressions", default=None,
|
||||
help="Add a suppressions files to memory leak checking.")
|
||||
parser.add_argument("--shell",
|
||||
default="./build/%s/tools/run" % (platform),
|
||||
help="Path to osquery run wrapper.")
|
||||
@ -198,6 +249,11 @@ if __name__ == "__main__":
|
||||
else:
|
||||
queries = queries_from_tables(args.tables, args.restrict)
|
||||
|
||||
if args.leaks:
|
||||
results = profile_leaks(args.shell, queries,
|
||||
supp_file=args.suppressions)
|
||||
exit(0)
|
||||
|
||||
# Start the profiling!
|
||||
results = profile(args.shell, queries,
|
||||
timeout=args.timeout, count=args.count, rounds=args.rounds)
|
||||
|
Loading…
Reference in New Issue
Block a user