in elastic-ebpf/GPL/Events/Process/Probe.bpf.c [87:176]
int BPF_PROG(sched_process_exec,
const struct task_struct *task,
pid_t old_pid,
const struct linux_binprm *binprm)
{
if (!binprm)
goto out;
// Note that we don't ignore the !is_thread_group_leader(task) case here.
// if a non-thread-group-leader thread performs an execve, it assumes the
// pid info of the thread group leader, all other threads are terminated,
// and it performs the exec. Thus a non-thread-group-leader performing an
// exec is valid and something we want to capture
if (is_kernel_thread(task))
goto out;
struct ebpf_process_exec_event *event = get_event_buffer();
if (!event)
goto out;
event->hdr.type = EBPF_EVENT_PROCESS_EXEC;
event->hdr.ts = bpf_ktime_get_ns();
event->hdr.ts_boot = bpf_ktime_get_boot_ns_helper();
ebpf_pid_info__fill(&event->pids, task);
ebpf_cred_info__fill(&event->creds, task);
ebpf_ctty__fill(&event->ctty, task);
ebpf_comm__fill(event->comm, sizeof(event->comm), task);
ebpf_ns__fill(&event->ns, task);
// set setuid and setgid flags
struct file *f = BPF_CORE_READ(binprm, file);
struct inode *f_inode = BPF_CORE_READ(f, f_inode);
event->flags = 0;
if (BPF_CORE_READ(f_inode, i_mode) & S_ISUID)
event->flags |= EXEC_F_SETUID;
if (BPF_CORE_READ(f_inode, i_mode) & S_ISGID)
event->flags |= EXEC_F_SETGID;
// set inode link count (0 means anonymous or deleted file)
event->inode_nlink = BPF_CORE_READ(f_inode, i_nlink);
// check if memfd file is being exec'd
struct path p = BPF_CORE_READ(binprm, file, f_path);
struct dentry *curr_dentry = BPF_CORE_READ(&p, dentry);
struct qstr component = BPF_CORE_READ(curr_dentry, d_name);
char buf_filename[sizeof(MEMFD_STRING)] = {0};
int ret = bpf_probe_read_kernel_str(buf_filename, sizeof(MEMFD_STRING), (void *)component.name);
if (ret <= 0) {
bpf_printk("could not read d_name at %p\n", component.name);
goto out;
}
if (is_equal_prefix(MEMFD_STRING, buf_filename, sizeof(MEMFD_STRING) - 1))
event->flags |= EXEC_F_MEMFD;
// Variable length fields
ebpf_vl_fields__init(&event->vl_fields);
struct ebpf_varlen_field *field;
long size;
// pids ss cgroup path
field = ebpf_vl_field__add(&event->vl_fields, EBPF_VL_FIELD_PIDS_SS_CGROUP_PATH);
size = ebpf_resolve_pids_ss_cgroup_path_to_string(field->data, task);
ebpf_vl_field__set_size(&event->vl_fields, field, size);
// argv
field = ebpf_vl_field__add(&event->vl_fields, EBPF_VL_FIELD_ARGV);
size = ebpf_argv__fill(field->data, ARGV_MAX, task);
ebpf_vl_field__set_size(&event->vl_fields, field, size);
// env
field = ebpf_vl_field__add(&event->vl_fields, EBPF_VL_FIELD_ENV);
size = ebpf_env__fill(field->data, ENV_MAX, task);
ebpf_vl_field__set_size(&event->vl_fields, field, size);
// cwd
field = ebpf_vl_field__add(&event->vl_fields, EBPF_VL_FIELD_CWD);
size = ebpf_resolve_path_to_string(field->data, &task->fs->pwd, task);
ebpf_vl_field__set_size(&event->vl_fields, field, size);
// filename
field = ebpf_vl_field__add(&event->vl_fields, EBPF_VL_FIELD_FILENAME);
size = read_kernel_str_or_empty_str(field->data, PATH_MAX, binprm->filename);
ebpf_vl_field__set_size(&event->vl_fields, field, size);
ebpf_ringbuf_write(&ringbuf, event, EVENT_SIZE(event), 0);
out:
return 0;
}