Skip to content

Commit

Permalink
bpf: Capture strings on syscall exit
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandrogario committed Sep 14, 2021
1 parent 31b24f9 commit 04de7d7
Show file tree
Hide file tree
Showing 6 changed files with 397 additions and 112 deletions.
2 changes: 2 additions & 0 deletions osquery/events/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ function(generateOsqueryEvents)
linux/bpf/processcontextfactory.cpp
linux/bpf/setrlimit.cpp
linux/bpf/systemstatetracker.cpp
linux/bpf/serializers.cpp
)
endif()

Expand Down Expand Up @@ -129,6 +130,7 @@ function(generateOsqueryEvents)
linux/bpf/processcontextfactory.h
linux/bpf/setrlimit.h
linux/bpf/systemstatetracker.h
linux/bpf/serializers.h
linux/bpf/uniquedir.h
)
endif()
Expand Down
150 changes: 44 additions & 106 deletions osquery/events/linux/bpf/bpfeventpublisher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <osquery/core/flags.h>
#include <osquery/events/linux/bpf/bpfeventpublisher.h>
#include <osquery/events/linux/bpf/serializers.h>
#include <osquery/events/linux/bpf/setrlimit.h>
#include <osquery/events/linux/bpf/systemstatetracker.h>
#include <osquery/logger/logger.h>
Expand Down Expand Up @@ -41,7 +42,6 @@ struct FunctionTracerAllocator final {
EventHandler event_handler;
std::uint8_t buffer_storage_pool{0U};
bool kprobe{false};
const ebpfpub::IFunctionTracer::ParameterList* parameter_list{nullptr};
};

std::unordered_set<std::string> kOptionalSyscallList{"openat2",
Expand All @@ -67,96 +67,39 @@ const std::string kKprobeSyscallPrefix{

using FunctionTracerAllocatorList = std::vector<FunctionTracerAllocator>;

const ebpfpub::IFunctionTracer::ParameterList kExecveKprobeParameterList = {
{"filename",
ebpfpub::IFunctionTracer::Parameter::Type::String,
ebpfpub::IFunctionTracer::Parameter::Mode::In,
{}},

{"argv",
ebpfpub::IFunctionTracer::Parameter::Type::Argv,
ebpfpub::IFunctionTracer::Parameter::Mode::In,
10U},

{"envp",
ebpfpub::IFunctionTracer::Parameter::Type::Integer,
ebpfpub::IFunctionTracer::Parameter::Mode::In,
8U}};

const ebpfpub::IFunctionTracer::ParameterList kExecveatKprobeParameterList = {
{"fd",
ebpfpub::IFunctionTracer::Parameter::Type::Integer,
ebpfpub::IFunctionTracer::Parameter::Mode::In,
8U},

{"filename",
ebpfpub::IFunctionTracer::Parameter::Type::String,
ebpfpub::IFunctionTracer::Parameter::Mode::In,
{}},

{"argv",
ebpfpub::IFunctionTracer::Parameter::Type::Argv,
ebpfpub::IFunctionTracer::Parameter::Mode::In,
10U},

{"envp",
ebpfpub::IFunctionTracer::Parameter::Type::Integer,
ebpfpub::IFunctionTracer::Parameter::Mode::In,
8U},

{"flags",
ebpfpub::IFunctionTracer::Parameter::Type::Integer,
ebpfpub::IFunctionTracer::Parameter::Mode::In,
8U}};

const FunctionTracerAllocatorList kFunctionTracerAllocators = {
{"fork", &BPFEventPublisher::processForkEvent, 0U, false, nullptr},
{"vfork", &BPFEventPublisher::processVforkEvent, 0U, false, nullptr},
{"clone", &BPFEventPublisher::processCloneEvent, 0U, false, nullptr},
{"close", &BPFEventPublisher::processCloseEvent, 0U, false, nullptr},
{"dup", &BPFEventPublisher::processDupEvent, 0U, false, nullptr},
{"dup2", &BPFEventPublisher::processDup2Event, 0U, false, nullptr},
{"dup3", &BPFEventPublisher::processDup3Event, 0U, false, nullptr},
{"creat", &BPFEventPublisher::processCreatEvent, 1U, false, nullptr},
{"mknod", &BPFEventPublisher::processMknodatEvent, 1U, false, nullptr},
{"mknodat", &BPFEventPublisher::processMknodatEvent, 1U, false, nullptr},
{"open", &BPFEventPublisher::processOpenEvent, 2U, false, nullptr},
{"openat", &BPFEventPublisher::processOpenatEvent, 2U, false, nullptr},
{"openat2", &BPFEventPublisher::processOpenat2Event, 1U, false, nullptr},
{"socket", &BPFEventPublisher::processSocketEvent, 4U, false, nullptr},
{"fcntl", &BPFEventPublisher::processFcntlEvent, 4U, false, nullptr},
{"connect", &BPFEventPublisher::processConnectEvent, 4U, false, nullptr},
{"accept", &BPFEventPublisher::processAcceptEvent, 4U, false, nullptr},
{"accept4", &BPFEventPublisher::processAccept4Event, 4U, false, nullptr},
{"bind", &BPFEventPublisher::processBindEvent, 4U, false, nullptr},
{"listen", &BPFEventPublisher::processListenEvent, 4U, false, nullptr},
{"chdir", &BPFEventPublisher::processChdirEvent, 5U, false, nullptr},
{"fchdir", &BPFEventPublisher::processFchdirEvent, 5U, false, nullptr},

{"fork", &BPFEventPublisher::processForkEvent, 0U, false},
{"vfork", &BPFEventPublisher::processVforkEvent, 0U, false},
{"clone", &BPFEventPublisher::processCloneEvent, 0U, false},
{"close", &BPFEventPublisher::processCloseEvent, 0U, false},
{"dup", &BPFEventPublisher::processDupEvent, 0U, false},
{"dup2", &BPFEventPublisher::processDup2Event, 0U, false},
{"dup3", &BPFEventPublisher::processDup3Event, 0U, false},
{"creat", &BPFEventPublisher::processCreatEvent, 1U, false},
{"mknod", &BPFEventPublisher::processMknodatEvent, 1U, false},
{"mknodat", &BPFEventPublisher::processMknodatEvent, 1U, false},
{"open", &BPFEventPublisher::processOpenEvent, 2U, false},
{"openat", &BPFEventPublisher::processOpenatEvent, 2U, false},
{"openat2", &BPFEventPublisher::processOpenat2Event, 1U, false},
{"socket", &BPFEventPublisher::processSocketEvent, 4U, false},
{"fcntl", &BPFEventPublisher::processFcntlEvent, 4U, false},
{"connect", &BPFEventPublisher::processConnectEvent, 4U, false},
{"accept", &BPFEventPublisher::processAcceptEvent, 4U, false},
{"accept4", &BPFEventPublisher::processAccept4Event, 4U, false},
{"bind", &BPFEventPublisher::processBindEvent, 4U, false},
{"listen", &BPFEventPublisher::processListenEvent, 4U, false},
{"chdir", &BPFEventPublisher::processChdirEvent, 5U, false},
{"fchdir", &BPFEventPublisher::processFchdirEvent, 5U, false},
{"name_to_handle_at",
&BPFEventPublisher::processNameToHandleAtEvent,
1U,
false,
nullptr},

false},
{"open_by_handle_at",
&BPFEventPublisher::processOpenByHandleAtEvent,
1U,
false,
nullptr},

{kKprobeSyscallPrefix + "execve",
&BPFEventPublisher::processExecveEvent,
3U,
true,
&kExecveKprobeParameterList},

{kKprobeSyscallPrefix + "execveat",
&BPFEventPublisher::processExecveatEvent,
3U,
true,
&kExecveatKprobeParameterList}};

false},
{"execve", &BPFEventPublisher::processExecveEvent, 3U, true},
{"execveat", &BPFEventPublisher::processExecveatEvent, 3U, true}};
} // namespace

FLAG(bool,
Expand Down Expand Up @@ -241,40 +184,43 @@ Status BPFEventPublisher::setUp() {

tob::StringErrorOr<ebpfpub::IFunctionTracer::Ref> function_tracer_exp;

const auto& parameter_list_it =
kParameterListMap.find(tracer_allocator.syscall_name);

if (tracer_allocator.kprobe) {
if (tracer_allocator.parameter_list == nullptr) {
LOG(WARNING) << "Skipping the kprobe for "
<< tracer_allocator.syscall_name
<< " due to missing parameter list";
if (parameter_list_it == kParameterListMap.end()) {
LOG(ERROR) << "Skipping the kprobe tracer for "
<< tracer_allocator.syscall_name
<< " due to missing parameter list";

continue;
}

auto& parameter_list = *tracer_allocator.parameter_list;
const auto& parameter_list = parameter_list_it->second;

function_tracer_exp = ebpfpub::IFunctionTracer::createFromKprobe(
tracer_allocator.syscall_name,
kKprobeSyscallPrefix + tracer_allocator.syscall_name,
parameter_list,
buffer_storage,
*d->perf_event_array.get(),
kEventMapSize);

} else {
if (tracer_allocator.parameter_list != nullptr) {
auto& parameter_list = *tracer_allocator.parameter_list;

if (parameter_list_it == kParameterListMap.end()) {
function_tracer_exp =
ebpfpub::IFunctionTracer::createFromSyscallTracepoint(
tracer_allocator.syscall_name,
parameter_list,
buffer_storage,
*d->perf_event_array.get(),
kEventMapSize);

} else {
const auto& parameter_list = parameter_list_it->second;

function_tracer_exp =
ebpfpub::IFunctionTracer::createFromSyscallTracepoint(
tracer_allocator.syscall_name,
parameter_list,
buffer_storage,
*d->perf_event_array.get(),
kEventMapSize);
Expand Down Expand Up @@ -672,7 +618,7 @@ bool BPFEventPublisher::processCreatEvent(
}

std::string path;
if (!getEventMapValue(path, event.in_field_map, "pathname")) {
if (!getEventMapValue(path, event.out_field_map, "pathname")) {
return false;
}

Expand Down Expand Up @@ -718,7 +664,7 @@ bool BPFEventPublisher::processMknodatEvent(
}

std::string pathname;
if (!getEventMapValue(pathname, event.in_field_map, "filename")) {
if (!getEventMapValue(pathname, event.out_field_map, "filename")) {
return false;
}

Expand Down Expand Up @@ -849,7 +795,7 @@ bool BPFEventPublisher::processOpenEvent(
}

std::string filename;
if (!getEventMapValue(filename, event.in_field_map, "filename")) {
if (!getEventMapValue(filename, event.out_field_map, "filename")) {
return false;
}

Expand Down Expand Up @@ -879,14 +825,6 @@ bool BPFEventPublisher::processOpenatEvent(
return false;
}

// It is possible for the memory page containing the filename string to
// not be mapped when we start executing our probe. Since BPF can't handle
// page faults, we would get back an empty string.
//
// To work around this issue, this parameter has been switch from IN to OUT
// in the tracepointserializers.cpp file, so that we capture this when exiting
// the syscall. This makes sure that the string is readable by the
// bpf_read_str helper
std::string filename;
if (!getEventMapValue(filename, event.out_field_map, "filename")) {
return false;
Expand Down Expand Up @@ -948,7 +886,7 @@ bool BPFEventPublisher::processChdirEvent(
}

std::string filename;
if (!getEventMapValue(filename, event.in_field_map, "filename")) {
if (!getEventMapValue(filename, event.out_field_map, "filename")) {
return false;
}

Expand Down

0 comments on commit 04de7d7

Please sign in to comment.