Skip to content

Commit

Permalink
ebpf: Fix missing parent issue in clone events
Browse files Browse the repository at this point in the history
Clone events are handled in event_wake_up_new_task program. In the
case of __event_find_parent failure, we do not send an event to the
user. On the other hand, execve_map_get has already added a new
entry in execve_map. This causes an inconsistency between execve_map
and the user space process cache that may lead for events to go through
the eventcache and waing of a process that never arrives.

To solve this, we try to find our parent in the beginning of the
program. If we fail to do so, we simply stop the execution of this
program (and do not add any entries in the execve_map). This commit
also does some refactoring to cleanup the code.

Signed-off-by: Anastasios Papagiannis <tasos.papagiannnis@gmail.com>
  • Loading branch information
tpapagian committed Nov 3, 2023
1 parent 6b4d4dc commit 41ca507
Showing 1 changed file with 41 additions and 32 deletions.
73 changes: 41 additions & 32 deletions bpf/process/bpf_fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,52 +21,61 @@ __attribute__((section("kprobe/wake_up_new_task"), used)) int
BPF_KPROBE(event_wake_up_new_task, struct task_struct *task)
{
struct execve_map_value *curr, *parent;
struct msg_clone_event msg;
u64 msg_size;
u32 tgid = 0;

if (!task)
return 0;

tgid = BPF_CORE_READ(task, tgid);

curr = execve_map_get(tgid);
if (!curr)
/* Generate an EVENT_COMMON_FLAG_CLONE event once per
* process, that is, thread group. Try to get it and
* check if it already exists.
*/
curr = execve_map_get_noinit(tgid);
if (curr)
return 0;

/* Generate an EVENT_COMMON_FLAG_CLONE event once per process,
* that is, thread group.
/* Do not try to create any msg or calling execve_map_get
* (that will add a new process in the execve_map) if we
* cannot find it's parent in the execve_map.
*/
if (curr->key.ktime != 0)
parent = __event_find_parent(task);
if (!parent)
return 0;

curr = execve_map_get(tgid);
if (!curr)
return 0;

/* Setup the execve_map entry. */
curr->flags = EVENT_COMMON_FLAG_CLONE;
parent = __event_find_parent(task);
if (parent) {
curr->key.pid = tgid;
curr->key.ktime = ktime_get_ns();
curr->nspid = get_task_pid_vnr();
curr->binary = parent->binary;
curr->pkey = parent->key;
curr->key.pid = tgid;
curr->key.ktime = ktime_get_ns();
curr->nspid = get_task_pid_vnr();
curr->binary = parent->binary;
curr->pkey = parent->key;

/* Setup the msg_clone_event and sent to the user. */
msg_size = sizeof(struct msg_clone_event);
msg.common.op = MSG_OP_CLONE;
msg.common.size = msg_size;
msg.common.ktime = curr->key.ktime;
msg.parent = curr->pkey;
msg.tgid = curr->key.pid;
/* Per thread tracking rules TID == PID :
* Since we generate one event per thread group, then when this task
* wakes up it will be the only one in the thread group, and it is
* the leader. Ensure to pass TID to user space.
*/
msg.tid = BPF_CORE_READ(task, pid);
msg.ktime = curr->key.ktime;
msg.nspid = curr->nspid;
msg.flags = curr->flags;

u64 size = sizeof(struct msg_clone_event);
struct msg_clone_event msg = {
.common.op = MSG_OP_CLONE,
.common.size = size,
.common.ktime = curr->key.ktime,
.parent = curr->pkey,
.tgid = curr->key.pid,
/**
* Per thread tracking rules TID == PID :
* Since we generate one event per thread group, then when this task
* wakes up it will be the only one in the thread group, and it is
* the leader. Ensure to pass TID to user space.
*/
.tid = BPF_CORE_READ(task, pid),
.ktime = curr->key.ktime,
.nspid = curr->nspid,
.flags = curr->flags,
};
perf_event_output_metric(ctx, MSG_OP_CLONE, &tcpmon_map, BPF_F_CURRENT_CPU, &msg, msg_size);

perf_event_output_metric(ctx, MSG_OP_CLONE, &tcpmon_map, BPF_F_CURRENT_CPU, &msg, size);
}
return 0;
}

0 comments on commit 41ca507

Please sign in to comment.