Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions agent/src/ebpf/kernel/include/socket_trace_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,8 @@ enum {
*/
EVENT_TYPE_MIN = 1 << 9,
EVENT_TYPE_PROC_EXEC = 1 << 9,
EVENT_TYPE_PROC_EXIT = 1 << 10
EVENT_TYPE_PROC_EXIT = 1 << 10,
EVENT_TYPE_LIB_LOAD = 1 << 11
// Add new event type here.
};

Expand All @@ -378,14 +379,20 @@ struct event_meta {
__u32 event_type;
};

// Process execution or exit event data
// Process execution or exit event data
struct process_event_t {
struct event_meta meta;
__u32 pid:31; // process ID
__u32 maybe_thread:1;
__u8 name[TASK_COMM_LEN]; // process name
};

// Library load event data (triggered by _dl_open uretprobe)
struct library_load_event_t {
struct event_meta meta;
__u32 pid; // process ID
};

struct debug_data {
__u16 magic;
__u8 fun;
Expand Down
19 changes: 19 additions & 0 deletions agent/src/ebpf/kernel/uprobe_base.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -774,3 +774,22 @@ TP_SCHED_PROG(process_exec) (struct sched_comm_exec_ctx *ctx)
{
return __process_exec((void *)ctx);
}

// uretprobe: fires when _dl_open() returns after dynamically loading a library.
// Attached from user-space via program__attach_uprobe() to ld-linux's _dl_open.
URETPROG(dl_open_uretprobe) (struct pt_regs *ctx)
{
struct member_fields_offset *offset = retrieve_ready_kern_offset();
if (offset == NULL)
return 0;

__u64 id = bpf_get_current_pid_tgid();
pid_t pid = id >> 32;

struct library_load_event_t data = {};
data.meta.event_type = EVENT_TYPE_LIB_LOAD;
data.pid = pid;
bpf_perf_event_output(ctx, &NAME(socket_data),
BPF_F_CURRENT_CPU, &data, sizeof(data));
return 0;
}
2 changes: 2 additions & 0 deletions agent/src/ebpf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ pub const MSG_CLOSE: u8 = 10;
pub const EVENT_TYPE_PROC_EXEC: u32 = 1 << 9;
#[allow(dead_code)]
pub const EVENT_TYPE_PROC_EXIT: u32 = 1 << 10;
#[allow(dead_code)]
pub const EVENT_TYPE_LIB_LOAD: u32 = 1 << 11;

// Profiler types
#[allow(dead_code)]
Expand Down
2 changes: 1 addition & 1 deletion agent/src/ebpf/user/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,7 +1087,7 @@ void process_event_free(struct process_create_event *event)
void add_event_to_proc_list(proc_event_list_t * list, struct bpf_tracer *tracer,
int pid, char *path)
{
static const uint32_t PROC_EVENT_HANDLE_DELAY = 120;
static const uint32_t PROC_EVENT_HANDLE_DELAY = 0;
struct process_create_event *event = NULL;

event = calloc(1, sizeof(struct process_create_event));
Expand Down
15 changes: 15 additions & 0 deletions agent/src/ebpf/user/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,16 @@ static inline int process_exists(pid_t pid)
return 0; // does not exist
}

static void library_load_event(struct library_load_event_t *e)
{
/*
* A shared library was loaded via dlopen(). Re-trigger the process
* initialization pipeline so that maps are rescanned and uprobes
* are attached for the newly loaded library.
*/
extended_process_exec(e->pid);
}

static void process_event(struct process_event_t *e)
{
if (e->meta.event_type == EVENT_TYPE_PROC_EXEC) {
Expand Down Expand Up @@ -992,6 +1002,11 @@ static int register_events_handle(struct reader_forward_info *fwd_info,
process_event((struct process_event_t *)meta);
}

// Handle library load events (dlopen detection).
if (meta->event_type == EVENT_TYPE_LIB_LOAD) {
library_load_event((struct library_load_event_t *)meta);
}

struct extra_event *e;
void (*fn) (void *) = NULL;
list_for_each_entry(e, &events_list, list) {
Expand Down
7 changes: 7 additions & 0 deletions agent/src/ebpf/user/tracer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2095,6 +2095,13 @@ bool is_pid_match(int feature, int pid)
return kv.value & (1UL << feature);
}

int add_feature_pid(int feature, int pid)
{
if (feature < 0 || feature >= FEATURE_MAX)
return -1;
return add_pid_to_match_hash(feature, pid);
}

static int clear_pid_from_match_hash(int feature, int pid)
{
int ret = 0;
Expand Down
1 change: 1 addition & 0 deletions agent/src/ebpf/user/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ int exec_set_feature_pids(int feature, const int *pids, int num);
int set_feature_pids(int feature, const int *pids, int num);
int init_match_pids_hash(void);
bool is_pid_match(int feature, int pid);
int add_feature_pid(int feature, int pid);
struct probe *create_probe(struct bpf_tracer *tracer,
const char *func_name, bool isret,
enum probe_type type, void *private,
Expand Down
14 changes: 14 additions & 0 deletions agent/src/ebpf_dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,20 @@ impl EbpfCollector {
warn!("ebpf start_continuous_profiler error.");
}

// Register the process event callback to receive real-time
// exec/exit notifications from the eBPF layer. This enables
// near-instant PID filter map updates instead of waiting for
// the 10-second /proc scan interval.
if ebpf::register_event_handle(
ebpf::EVENT_TYPE_PROC_EXEC | ebpf::EVENT_TYPE_PROC_EXIT,
crate::utils::process::process_event_callback,
) != 0
{
warn!("ebpf register_event_handle for process events failed");
} else {
info!("ebpf register_event_handle for process events succeeded");
}

if !is_uprobe_meltdown && !on_cpu.disabled {
let feature = "ebpf.profile.on_cpu";
process_listener.register(feature, set_feature_on_cpu);
Expand Down
Loading