Skip to content

Commit

Permalink
eBPF tracking program for any syscall exit event (osquery#5403)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: osquery#5403

Part of a linux  tracing system, blueprint: [osquery#5218](osquery#5218)

Reviewed By: SAlexandru

Differential Revision: D13690684

fbshipit-source-id: 039fc89929de49fcc7bd2287a98ffc68450fcada
  • Loading branch information
akindyakov authored and Nick Anderson committed Feb 1, 2019
1 parent 2c2d415 commit 66cf603
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
16 changes: 15 additions & 1 deletion osquery/events/linux/probes/syscall_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,19 @@ namespace syscall {
enum class Type : __s32 {
Unknown = 0,
KillEnter = 1,
KillExit = -KillEnter,
};

static constexpr std::size_t kCommSize = 16u;

struct Event {
Type type; // ebpf offset depends on the struct type in the unit
// Common part for all events whether Enter or Exit
Type type;
__s32 pid;
__s32 tgid;

// Body means different things for each Enter type.
// For all Exit types Body is always the same - just return value.
union Body {
struct KillEnter {
/* -44 type */
Expand All @@ -41,7 +45,17 @@ struct Event {
/* -8 */ __u32 uid;
/* -4 */ __u32 gid;
} kill_enter;

struct Exit {
/* -16 type */
/* -12 pid */
/* -8 tgid */
/* -4 */ __s32 ret;
} exit;
} body;

// final return value of the syscall is palced here by EnterExitJoiner
__s32 return_value;
};

} // namespace syscall
Expand Down
42 changes: 42 additions & 0 deletions osquery/events/linux/probes/syscalls_programs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,47 @@ Expected<ebpf::Program, ebpf::Program::Error> genLinuxKillEnterProgram(
// clang-format on
}

Expected<ebpf::Program, ebpf::Program::Error> genLinuxExitProgram(
enum bpf_prog_type prog_type,
PerfEventCpuMap const& cpu_map,
syscall::Type type) {
constexpr int kExitSize = 16;
static_assert(sizeof(syscall::Type) + sizeof(syscall::Event::pid) +
sizeof(syscall::Event::tgid) +
sizeof(syscall::Event::Body::Exit) ==
kExitSize,
"A program below relies on certain size of output struct");
// clang-format off
return ebpf::Program::load({
// code , dst reg , src reg , offset , immediate constant(k)
{BPF_ALU64 | BPF_X | BPF_MOV , BPF_REG_6, BPF_REG_1, 0, 0}, // r6 = r1
{BPF_ALU64 | BPF_K | BPF_MOV , BPF_REG_1, 0, 0, 0}, // r1 = 0

{BPF_ST | BPF_W | BPF_MEM , BPF_REG_10, 0, -kExitSize, static_cast<__s32>(type)}, // type = syscall::Type::Exit*

{BPF_JMP | BPF_K | BPF_CALL , 0, 0, 0, BPF_FUNC_get_current_pid_tgid},
{BPF_STX | BPF_W | BPF_MEM , BPF_REG_10, BPF_REG_0, -12, 0}, // Event.pid
{BPF_ALU64 | BPF_K | BPF_RSH , 0, 0, 0, 32}, // r0 >>= 32
{BPF_STX | BPF_W | BPF_MEM , BPF_REG_10, BPF_REG_0, -8, 0}, // Event.tgid

{BPF_LDX | BPF_DW | BPF_MEM , BPF_REG_7, BPF_REG_6, 16, 0}, // see format: ret
{BPF_STX | BPF_W | BPF_MEM , BPF_REG_10, BPF_REG_7, -4, 0}, // Event.body.return_value

{BPF_ALU64 | BPF_X | BPF_MOV , BPF_REG_4, BPF_REG_10, 0, 0}, // r4 = r10
{BPF_ALU64 | BPF_K | BPF_ADD , BPF_REG_4, 0, 0, -kExitSize}, // r4 += -kExitSize
{BPF_ALU64 | BPF_X | BPF_MOV , BPF_REG_1, BPF_REG_6, 0, 0}, // r1 = r6
{BPF_LD | BPF_DW | BPF_IMM , BPF_REG_2, BPF_PSEUDO_MAP_FD, 0, cpu_map.fd()},
{BPF_LD | BPF_W | BPF_IMM , 0, 0, 0, 0}, // imm is 32, but we loading 64, so this is yet another "smart" trick
{BPF_LD | BPF_DW | BPF_IMM , BPF_REG_3, 0, 0, -1}, // r2 = -1 -> CPU
{BPF_LD | BPF_W | BPF_IMM , 0, 0, 0, 0}, // imm is 32, but we loading 64, so this is yet another "smart" trick
{BPF_ALU64 | BPF_K | BPF_MOV , BPF_REG_5, 0, 0, kExitSize}, // r5 = kExitSize
{BPF_JMP | BPF_K | BPF_CALL , 0, 0, 0, BPF_FUNC_perf_event_output}, // call
{BPF_ALU64 | BPF_K | BPF_MOV , BPF_REG_0, 0, 0, 0}, // r0 = 0
{BPF_JMP | BPF_K | BPF_EXIT , 0, 0, 0, 0}, // exit

}, BPF_PROG_TYPE_TRACEPOINT, kIsDebug);
// clang-format on
}

} // namespace events
} // namespace osquery
5 changes: 5 additions & 0 deletions osquery/events/linux/probes/syscalls_programs.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,10 @@ using PerfEventCpuMap = ebpf::Map<int, int, BPF_MAP_TYPE_PERF_EVENT_ARRAY>;
Expected<ebpf::Program, ebpf::Program::Error> genLinuxKillEnterProgram(
enum bpf_prog_type prog_type, PerfEventCpuMap const& cpu_map);

Expected<ebpf::Program, ebpf::Program::Error> genLinuxExitProgram(
enum bpf_prog_type prog_type,
PerfEventCpuMap const& cpu_map,
syscall::Type type);

} // namespace events
} // namespace osquery

0 comments on commit 66cf603

Please sign in to comment.