forked from osquery/osquery
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Linux kill() enter/exit ebpf programs definitions (osquery#5386)
Summary: Pull Request resolved: osquery#5386 Part of a linux tracing system, blueprint: [osquery#5218](osquery#5218) Reviewed By: SAlexandru Differential Revision: D13654124 fbshipit-source-id: 8db63e584bd772132c1ba1c80853c60613e8036a
- Loading branch information
1 parent
c3c0e5f
commit 2c2d415
Showing
5 changed files
with
207 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/** | ||
* Copyright (c) 2014-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under both the Apache 2.0 license (found in the | ||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found | ||
* in the COPYING file in the root directory of this source tree). | ||
* You may select, at your option, one of the above-listed licenses. | ||
*/ | ||
|
||
#include <osquery/events/linux/probes/syscall_event.h> | ||
|
||
namespace osquery { | ||
namespace events {} // namespace events | ||
} // namespace osquery |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* Copyright (c) 2014-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under both the Apache 2.0 license (found in the | ||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found | ||
* in the COPYING file in the root directory of this source tree). | ||
* You may select, at your option, one of the above-listed licenses. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <osquery/utils/expected/expected.h> | ||
#include <osquery/utils/system/linux/ebpf/program.h> | ||
|
||
namespace osquery { | ||
namespace events { | ||
|
||
namespace syscall { | ||
|
||
enum class Type : __s32 { | ||
Unknown = 0, | ||
KillEnter = 1, | ||
}; | ||
|
||
static constexpr std::size_t kCommSize = 16u; | ||
|
||
struct Event { | ||
Type type; // ebpf offset depends on the struct type in the unit | ||
__s32 pid; | ||
__s32 tgid; | ||
|
||
union Body { | ||
struct KillEnter { | ||
/* -44 type */ | ||
/* -40 pid */ | ||
/* -36 tgid */ | ||
/* -32 */ char comm[kCommSize]; | ||
/* -16 */ __s32 arg_pid; | ||
/* -12 */ __s32 arg_sig; | ||
/* -8 */ __u32 uid; | ||
/* -4 */ __u32 gid; | ||
} kill_enter; | ||
} body; | ||
}; | ||
|
||
} // namespace syscall | ||
} // namespace events | ||
} // namespace osquery |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/** | ||
* Copyright (c) 2014-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under both the Apache 2.0 license (found in the | ||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found | ||
* in the COPYING file in the root directory of this source tree). | ||
* You may select, at your option, one of the above-listed licenses. | ||
*/ | ||
|
||
#include <osquery/events/linux/probes/syscalls_programs.h> | ||
|
||
namespace osquery { | ||
namespace events { | ||
|
||
namespace { | ||
|
||
bool constexpr kIsDebug = | ||
#ifndef NDEBUG | ||
true; | ||
#else | ||
false; | ||
#endif | ||
|
||
} // namespace | ||
|
||
Expected<ebpf::Program, ebpf::Program::Error> genLinuxKillEnterProgram( | ||
enum bpf_prog_type prog_type, PerfEventCpuMap const& cpu_map) { | ||
constexpr int kKillEnterSize = 44; | ||
static_assert(sizeof(syscall::Type) + sizeof(syscall::Event::pid) + | ||
sizeof(syscall::Event::tgid) + | ||
sizeof(syscall::Event::Body::KillEnter) == | ||
kKillEnterSize, | ||
"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 | ||
|
||
// this part of the stack is for comm string, let's initialize it with a '\0' | ||
{BPF_STX | BPF_DW | BPF_MEM , BPF_REG_10, BPF_REG_1, -32, 0}, | ||
{BPF_STX | BPF_DW | BPF_MEM , BPF_REG_10, BPF_REG_1, -24, 0}, | ||
|
||
// put syscall code into final event struct, @see syscall::Event::type | ||
{BPF_ST | BPF_W | BPF_MEM , BPF_REG_10, 0, -kKillEnterSize, static_cast<__s32>(syscall::Type::KillEnter)}, // Event.type | ||
|
||
// call fanction get_current_uid_gid() | ||
{BPF_JMP | BPF_K | BPF_CALL , 0, 0, 0, BPF_FUNC_get_current_uid_gid}, | ||
// put first [0..32] bits of return value (R0) which is uid into final event struct, offset -8 | ||
{BPF_STX | BPF_W | BPF_MEM , BPF_REG_10, BPF_REG_0, -8, 0}, // Event.uid | ||
{BPF_ALU64 | BPF_K | BPF_RSH , 0, 0, 0, 32}, | ||
// put first [32..65] bits of return value (R0) which is gid into final event struct, offset -4 | ||
{BPF_STX | BPF_W | BPF_MEM , BPF_REG_10, BPF_REG_0, -4, 0}, // Event.gid | ||
|
||
// call fanction get_current_pid_tgid() | ||
{BPF_JMP | BPF_K | BPF_CALL , 0, 0, 0, BPF_FUNC_get_current_pid_tgid}, | ||
// put first [0..32] bits of return value (R0) which is pid into final event struct, offset -40 | ||
{BPF_STX | BPF_W | BPF_MEM , BPF_REG_10, BPF_REG_0, -40, 0}, // Event.body.kill_enter.pid | ||
{BPF_ALU64 | BPF_K | BPF_RSH , 0, 0, 0, 32}, | ||
// put first [0..32] bits of return value (R0) which is tgid into final event struct, offset -36 | ||
{BPF_STX | BPF_W | BPF_MEM , BPF_REG_10, BPF_REG_0, -36, 0}, // Event.body.kill_enter.tgid | ||
|
||
// put stack pointer (register R10) to register R1, it's gonna be a first argument | ||
{BPF_ALU64 | BPF_X | BPF_MOV , BPF_REG_1, BPF_REG_10, 0, 0}, // r1 = r10 | ||
// make R1 pointing to Event.body.kill_enter.comm in final event struct, offset -32 | ||
{BPF_ALU64 | BPF_K | BPF_ADD , BPF_REG_1, 0, 0, -32}, // r1 += -32 | ||
// put size of Event.body.kill_enter.comm to R2, it's gonna be a second argument | ||
{BPF_ALU64 | BPF_K | BPF_MOV , BPF_REG_2, 0, 0, syscall::kCommSize}, | ||
// call get_current_comm(char *buf=R1, int size_of_buf=R2) | ||
{BPF_JMP | BPF_K | BPF_CALL , 0, 0, 0, BPF_FUNC_get_current_comm}, // call | ||
|
||
// let's read arguments of kill syscall, see /sys/kernel/debug/tracing/events/syscalls/sys_enter_kill/format | ||
// TODO: It's not portable, because format can differ on different systems, but let me fix it later. | ||
// load value from ctx + 16 to R7, accordint to format it is PID - first argument of kill() | ||
{BPF_LDX | BPF_DW | BPF_MEM , BPF_REG_7, BPF_REG_6, 16, 0}, | ||
// stor PID from R7 to final event struct on stack | ||
{BPF_STX | BPF_W | BPF_MEM , BPF_REG_10, BPF_REG_7, -16, 0}, | ||
// load value from ctx + 24 to R7, accordint to format it is SIG - second argument of kill() | ||
{BPF_LDX | BPF_DW | BPF_MEM , BPF_REG_7, BPF_REG_6, 24, 0}, | ||
// stor SIG from R7 to final event struct on stack | ||
{BPF_STX | BPF_W | BPF_MEM , BPF_REG_10, BPF_REG_7, -12, 0}, | ||
|
||
// let's send everything to user space via perf_event_open() | ||
// event located on top of the stack, so store pointer to the top of the stack (R10) to R4 | ||
{BPF_ALU64 | BPF_X | BPF_MOV , BPF_REG_4, BPF_REG_10, 0, 0}, | ||
// we need pointer to the beginning of the event, so substruct size of the sending struct from R4 | ||
{BPF_ALU64 | BPF_K | BPF_ADD , BPF_REG_4, 0, 0, -kKillEnterSize}, // r4 += -kKillEnterSize | ||
// store ctx to R1 | ||
{BPF_ALU64 | BPF_X | BPF_MOV , BPF_REG_1, BPF_REG_6, 0, 0}, | ||
// store map with perf_event_open() buffers per CPU to R2 | ||
{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 | ||
// we don't know current CPU, but kernel can take care of it, put -1 in R2 | ||
{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 | ||
// R5 should be a size of the event | ||
{BPF_ALU64 | BPF_K | BPF_MOV , BPF_REG_5, 0, 0, kKillEnterSize}, // r5 = kKillEnterSize | ||
// call perf_event_output(ctx=R1, map=R2, flags=R3, data=R4, size=R5) | ||
{BPF_JMP | BPF_K | BPF_CALL , 0, 0, 0, BPF_FUNC_perf_event_output}, // call | ||
// put 0 as a return value of the program | ||
{BPF_ALU64 | BPF_K | BPF_MOV , BPF_REG_0, 0, 0, 0}, // r0 = 0 | ||
// let's get out of here | ||
{BPF_JMP | BPF_K | BPF_EXIT , 0, 0, 0, 0}, // exit | ||
|
||
}, BPF_PROG_TYPE_TRACEPOINT, kIsDebug); | ||
// clang-format on | ||
} | ||
|
||
} // namespace events | ||
} // namespace osquery |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* Copyright (c) 2014-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under both the Apache 2.0 license (found in the | ||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found | ||
* in the COPYING file in the root directory of this source tree). | ||
* You may select, at your option, one of the above-listed licenses. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <osquery/events/linux/probes/syscall_event.h> | ||
|
||
#include <osquery/utils/expected/expected.h> | ||
#include <osquery/utils/system/linux/ebpf/map.h> | ||
#include <osquery/utils/system/linux/ebpf/program.h> | ||
|
||
namespace osquery { | ||
namespace events { | ||
|
||
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); | ||
|
||
} // namespace events | ||
} // namespace osquery |