int BPF_PROG()

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;
}