Skip to content

Commit

Permalink
Add config map and verify configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
yanivagman committed Dec 26, 2019
1 parent 649b19f commit 6d1effc
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 60 deletions.
7 changes: 3 additions & 4 deletions start.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ def parse_args(input_args):
epilog=examples)
parser.add_argument("-c", "--container", action="store_true",
help="only trace newly created containers")
parser.add_argument("--max-args", default="20",
help="maximum number of arguments parsed and displayed, defaults to 20")
parser.add_argument("-b", "--buf-pages", default="32",
help="number of pages for perf buffer, defaults to 32")
parser.add_argument("-b", "--buf-pages", type=int, default=64,
choices=[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024],
help="number of pages for perf buffer, defaults to %(default)s")
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
parser.add_argument("-j", "--json", action="store_true",
Expand Down
109 changes: 65 additions & 44 deletions tracee/event_monitor_ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/security.h>
#include <linux/version.h>

#define MAXARG 20
#define MAX_STRING_SIZE 4096 // Choosing this value to be the same as PATH_MAX
#define SUBMIT_BUFSIZE (2 << 13) // Need to be power of 2
#define SUBMIT_BUFSIZE_HALF ((SUBMIT_BUFSIZE-1) >> 1) // Bitmask for ebpf validator - this is why we need SUBMIT_BUFSIZE to be power of 2
Expand All @@ -38,6 +39,8 @@
#define CAP_T 17UL
#define TYPE_MAX 255UL

#define CONFIG_CONT_MODE 0

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
#error Minimal required kernel version is 4.14
#endif
Expand Down Expand Up @@ -426,6 +429,7 @@ struct uts_namespace {

/*=================================== MAPS =====================================*/

BPF_HASH(config_map, u32, u32); // Various configurations
BPF_HASH(pids_map, u32, u32); // Save container pid namespaces
BPF_HASH(args_map, u64, args_t); // Persist args info between function entry and return
BPF_PERCPU_ARRAY(submission_buf, submit_buf_t, 1); // Buffer used to prepare event for perf_submit
Expand Down Expand Up @@ -587,13 +591,24 @@ static __always_inline void remove_pid_ns_if_needed()
}
}

static __always_inline int container_mode()
{
u32 key = CONFIG_CONT_MODE;
u32 *mode = config_map.lookup(&key);

if (mode == NULL)
return 0;

return *mode;
}

static __always_inline int init_context(context_t *context)
{
struct task_struct *task;
task = (struct task_struct *)bpf_get_current_task();

u32 should_trace = 0;
if (CONTAINER_MODE)
if (container_mode())
should_trace = lookup_pid_ns(task);
else
should_trace = lookup_pid();
Expand All @@ -602,7 +617,7 @@ static __always_inline int init_context(context_t *context)
if (should_trace == 0)
return -1;

if (CONTAINER_MODE) {
if (container_mode()) {
context->tid = get_task_ns_pid(task);
context->pid = get_task_ns_tgid(task);
context->ppid = get_task_ns_ppid(task);
Expand Down Expand Up @@ -754,7 +769,7 @@ static __always_inline int save_args(struct pt_regs *ctx, bool is_syscall)
args_t args = {};

u32 should_trace = 0;
if (CONTAINER_MODE)
if (container_mode())
should_trace = is_container();
else
should_trace = lookup_pid();
Expand Down Expand Up @@ -891,57 +906,69 @@ static __always_inline int save_args_to_submit_buf(u64 types)
return 0;
}

static __always_inline int trace_ret_generic(struct pt_regs *ctx, u32 id, u64 types)
{
context_t context = {};

if (init_context(&context) || init_submit_buf())
return 0;

context.eventid = id;
context.argnum = get_encoded_arg_num(types);
context.retval = PT_REGS_RC(ctx);
save_to_submit_buf((void*)&context, sizeof(context_t), NONE_T);
save_args_to_submit_buf(types);

events_perf_submit(ctx);
return 0;
}

static __always_inline int trace_ret_generic_fork(struct pt_regs *ctx, u32 id, u64 types)
{
context_t context = {};

if (init_context(&context) || init_submit_buf())
return 0;

if (!container_mode()) {
u32 pid = PT_REGS_RC(ctx);
add_pid_fork(pid);
}

context.eventid = id;
context.argnum = get_encoded_arg_num(types);
context.retval = PT_REGS_RC(ctx);
save_to_submit_buf((void*)&context, sizeof(context_t), NONE_T);
save_args_to_submit_buf(types);

events_perf_submit(ctx);
return 0;
}

#define TRACE_ENT_SYSCALL(name) \
int syscall__##name(struct pt_regs *ctx) \
{ \
return save_args(ctx, true); \
}

#define TRACE_ENT_FUNC(name) \
int syscall__##name(struct pt_regs *ctx) \
int func__##name(struct pt_regs *ctx) \
{ \
return save_args(ctx, false); \
}

#define TRACE_RET_FUNC(name, id, types) \
int trace_ret_##name(struct pt_regs *ctx) \
{ \
context_t context = {}; \
\
if (init_context(&context) || init_submit_buf()) \
return 0; \
\
context.eventid = id; \
context.argnum = get_encoded_arg_num(types); \
context.retval = PT_REGS_RC(ctx); \
save_to_submit_buf((void*)&context, sizeof(context_t), NONE_T); \
save_args_to_submit_buf(types); \
\
events_perf_submit(ctx); \
return 0; \
return trace_ret_generic(ctx, id, types); \
}

#define TRACE_RET_SYSCALL TRACE_RET_FUNC

#define TRACE_RET_FORK_SYSCALL(name, id, types) \
int trace_ret_##name(struct pt_regs *ctx) \
{ \
context_t context = {}; \
\
if (init_context(&context) || init_submit_buf()) \
return 0; \
\
u32 pid = PT_REGS_RC(ctx); \
add_pid_fork(pid); \
\
context.eventid = id; \
context.argnum = get_encoded_arg_num(types); \
context.retval = PT_REGS_RC(ctx); \
save_to_submit_buf((void*)&context, sizeof(context_t), NONE_T); \
save_args_to_submit_buf(types); \
\
events_perf_submit(ctx); \
return 0; \
return trace_ret_generic_fork(ctx, id, types); \
}

/*============================== SYSCALL HOOKS ==============================*/
Expand Down Expand Up @@ -1032,17 +1059,11 @@ TRACE_ENT_SYSCALL(unlinkat);
TRACE_RET_SYSCALL(unlinkat, SYS_UNLINKAT, ARG_TYPE0(INT_T)|ARG_TYPE1(STR_T)|ARG_TYPE2(INT_T));

TRACE_ENT_SYSCALL(fork);
TRACE_ENT_SYSCALL(vfork);
TRACE_ENT_SYSCALL(clone);
#if CONTAINER_MODE
TRACE_RET_SYSCALL(fork, SYS_FORK, 0);
TRACE_RET_SYSCALL(vfork, SYS_VFORK, 0);
TRACE_RET_SYSCALL(clone, SYS_CLONE, 0);
#else
TRACE_RET_FORK_SYSCALL(fork, SYS_FORK, 0);
TRACE_ENT_SYSCALL(vfork);
TRACE_RET_FORK_SYSCALL(vfork, SYS_VFORK, 0);
TRACE_ENT_SYSCALL(clone);
TRACE_RET_FORK_SYSCALL(clone, SYS_CLONE, 0);
#endif

int syscall__execve(struct pt_regs *ctx,
const char __user *filename,
Expand All @@ -1052,7 +1073,7 @@ int syscall__execve(struct pt_regs *ctx,
context_t context = {};

u32 ret = 0;
if (CONTAINER_MODE)
if (container_mode())
ret = add_pid_ns_if_needed();
else
ret = add_pid();
Expand Down Expand Up @@ -1118,7 +1139,7 @@ int syscall__execveat(struct pt_regs *ctx,
context_t context = {};

u32 ret = 0;
if (CONTAINER_MODE)
if (container_mode())
ret = add_pid_ns_if_needed();
else
ret = add_pid();
Expand Down Expand Up @@ -1190,7 +1211,7 @@ int trace_do_exit(struct pt_regs *ctx, long code)
context.argnum = 0;
context.retval = code;

if (CONTAINER_MODE)
if (container_mode())
remove_pid_ns_if_needed();
else
remove_pid();
Expand Down
20 changes: 8 additions & 12 deletions tracee/tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
log.addHandler(handler)

BPF_PROGRAM = "tracee/event_monitor_ebpf.c"
MAX_ARGS = 20

# include/uapi/linux/capability.h
capabilities = {
Expand Down Expand Up @@ -501,6 +500,9 @@ class ArgType(object):
CAP_T = 17
TYPE_MAX = 255

class shared_config(object):
CONFIG_CONT_MODE = 0

class context_t(ctypes.Structure): # match layout of eBPF C's context_t struct
_fields_ = [("ts", ctypes.c_uint64),
("pid", ctypes.c_uint32),
Expand Down Expand Up @@ -758,17 +760,7 @@ def __init__(self, args):
self.buf_pages = args.buf_pages

def init_bpf(self):
bpf_text = load_bpf_program().replace("MAXARG", str(MAX_ARGS))
if self.cont_mode:
bpf_text = bpf_text.replace("CONTAINER_MODE", "1")
else:
bpf_text = bpf_text.replace("CONTAINER_MODE", "0")

try:
self.buf_pages = int(self.buf_pages)
except ValueError:
print("Invalid buffer size")
exit()
bpf_text = load_bpf_program()

if self.list_events:
log.info("Syscalls:")
Expand All @@ -786,6 +778,10 @@ def init_bpf(self):
# initialize BPF
self.bpf = BPF(text=bpf_text)

# set shared config
key = ctypes.c_uint32(shared_config.CONFIG_CONT_MODE)
self.bpf["config_map"][key] = ctypes.c_uint32(self.cont_mode)

# attaching kprobes
sk, se = get_kprobes(self.events_to_trace)

Expand Down

0 comments on commit 6d1effc

Please sign in to comment.