diff --git a/agent/src/ebpf/test/test_match_pids.c b/agent/src/ebpf/test/test_match_pids.c index 0e8a9e2f315..777a8c46dc6 100644 --- a/agent/src/ebpf/test/test_match_pids.c +++ b/agent/src/ebpf/test/test_match_pids.c @@ -49,28 +49,31 @@ int main(void) log_to_stdout = true; init_match_pids_hash(); int pids[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - int ret = set_feature_pids(FEATURE_PROFILE_ONCPU, pids, - sizeof(pids) / sizeof(pids[0])); - printf(" FEATURE_PROFILE_ONCPU set_feature_pids ret : %d\n", ret); + int ret = exec_set_feature_pids(FEATURE_PROFILE_ONCPU, pids, + sizeof(pids) / sizeof(pids[0])); + printf(" FEATURE_PROFILE_ONCPU exec_set_feature_pids ret : %d\n", ret); ret = - set_feature_pids(FEATURE_PROFILE_OFFCPU, pids, - sizeof(pids) / sizeof(pids[0])); - printf(" FEATURE_PROFILE_OFFCPU set_feature_pids ret : %d\n", ret); + exec_set_feature_pids(FEATURE_PROFILE_OFFCPU, pids, + sizeof(pids) / sizeof(pids[0])); + printf(" FEATURE_PROFILE_OFFCPU exec_set_feature_pids ret : %d\n", + ret); { int pids[] = { 11, 12, 34, 2000 }; ret = - set_feature_pids(FEATURE_PROFILE_ONCPU, pids, - sizeof(pids) / sizeof(pids[0])); - printf(" FEATURE_PROFILE_ONCPU set_feature_pids ret : %d\n", - ret); + exec_set_feature_pids(FEATURE_PROFILE_ONCPU, pids, + sizeof(pids) / sizeof(pids[0])); + printf + (" FEATURE_PROFILE_ONCPU exec_set_feature_pids ret : %d\n", + ret); } { int pids[] = { 1 }; ret = - set_feature_pids(FEATURE_PROFILE_ONCPU, pids, - sizeof(pids) / sizeof(pids[0])); - printf(" FEATURE_PROFILE_ONCPU set_feature_pids ret : %d\n", - ret); + exec_set_feature_pids(FEATURE_PROFILE_ONCPU, pids, + sizeof(pids) / sizeof(pids[0])); + printf + (" FEATURE_PROFILE_ONCPU exec_set_feature_pids ret : %d\n", + ret); count = 0; print_match_pids_hash(); } diff --git a/agent/src/ebpf/user/go_tracer.c b/agent/src/ebpf/user/go_tracer.c index 8768fa87d55..ae2a71819c5 100644 --- a/agent/src/ebpf/user/go_tracer.c +++ b/agent/src/ebpf/user/go_tracer.c @@ -58,6 +58,7 @@ struct process_event { uint8_t type; // EVENT_TYPE_PROC_EXEC or EVENT_TYPE_PROC_EXIT char *path; // Full path "/proc//root/..." int pid; // Process ID + uint64_t stime; // The start time of the process uint32_t expire_time; // Expiration Date, the number of seconds since the system started. }; /* *INDENT-ON* */ @@ -744,10 +745,6 @@ int collect_go_uprobe_syms_from_procfs(struct tracer_probes_conf *conf) struct dirent *entry = NULL; DIR *fddir = NULL; - init_list_head(&proc_events_head); - init_list_head(&proc_info_head); - pthread_mutex_init(&mutex_proc_events_lock, NULL); - if (!is_feature_enabled(FEATURE_UPROBE_GOLANG)) return ETR_OK; @@ -1018,6 +1015,7 @@ static void add_event_to_proc_header(struct bpf_tracer *tracer, int pid, pe->path = path; pe->pid = pid; pe->type = type; + pe->stime = get_process_starttime(pid); pe->expire_time = get_sys_uptime() + PROC_EVENT_DELAY_HANDLE_DEF; pthread_mutex_lock(&mutex_proc_events_lock); @@ -1036,9 +1034,6 @@ void go_process_exec(int pid) if (tracer == NULL) return; - if (tracer->state != TRACER_RUNNING) - return; - if (tracer->probes_count > OPEN_FILES_MAX) { ebpf_warning("Probes count too many. The maximum is %d\n", OPEN_FILES_MAX); @@ -1062,9 +1057,6 @@ void go_process_exit(int pid) if (tracer == NULL) return; - if (tracer->state != TRACER_RUNNING) - return; - process_exit_handle(pid, tracer); } @@ -1098,6 +1090,12 @@ void go_process_events_handle(void) free(pe->path); free(pe); pthread_mutex_unlock(&mutex_proc_events_lock); + // Confirm whether the process has changed? + if (pe->stime != get_process_starttime(pid)) { + free(path); + continue; + } + if (type == EVENT_TYPE_PROC_EXEC) { if (access(path, F_OK) == 0) { process_execute_handle(pid, tracer); @@ -1111,3 +1109,19 @@ void go_process_events_handle(void) } } while (true); } + +void golang_trace_handle(int pid, enum match_pids_act act) +{ + if (act == MATCH_PID_ADD) { + go_process_exec(pid); + } else { + go_process_exit(pid); + } +} + +void golang_trace_init(void) +{ + init_list_head(&proc_events_head); + init_list_head(&proc_info_head); + pthread_mutex_init(&mutex_proc_events_lock, NULL); +} diff --git a/agent/src/ebpf/user/go_tracer.h b/agent/src/ebpf/user/go_tracer.h index 69560517ab1..40e63510baa 100644 --- a/agent/src/ebpf/user/go_tracer.h +++ b/agent/src/ebpf/user/go_tracer.h @@ -47,4 +47,6 @@ void update_proc_info_to_map(struct bpf_tracer *tracer); void go_process_exec(int pid); void go_process_exit(int pid); void go_process_events_handle(void); +void golang_trace_handle(int pid, enum match_pids_act act); +void golang_trace_init(void); #endif diff --git a/agent/src/ebpf/user/proc.c b/agent/src/ebpf/user/proc.c index 98ba1613724..461ddc6b0ee 100644 --- a/agent/src/ebpf/user/proc.c +++ b/agent/src/ebpf/user/proc.c @@ -1041,12 +1041,12 @@ void add_event_to_proc_list(proc_event_list_t *list, struct bpf_tracer *tracer, event->tracer = tracer; event->pid = pid; + event->stime = get_process_starttime(pid); event->expire_time = get_sys_uptime() + PROC_EVENT_HANDLE_DELAY; pthread_mutex_lock(&list->m); list_add_tail(&event->list, &list->head); pthread_mutex_unlock(&list->m); - return; } struct process_create_event *get_first_event(proc_event_list_t *list) diff --git a/agent/src/ebpf/user/proc.h b/agent/src/ebpf/user/proc.h index 336ef35a4e0..6104b237773 100644 --- a/agent/src/ebpf/user/proc.h +++ b/agent/src/ebpf/user/proc.h @@ -203,6 +203,7 @@ bool process_probing_check(int pid); struct process_create_event { struct list_head list; int pid; + uint64_t stime; // Process start time uint32_t expire_time; struct bpf_tracer *tracer; }; diff --git a/agent/src/ebpf/user/socket.c b/agent/src/ebpf/user/socket.c index 4f75affade9..54d6b724f2c 100644 --- a/agent/src/ebpf/user/socket.c +++ b/agent/src/ebpf/user/socket.c @@ -329,10 +329,6 @@ static void socket_tracer_set_probes(struct tracer_probes_conf *tps) config_probes_for_kfunc(tps); else config_probes_for_kprobe_and_tracepoint(tps); - - // 收集go可执行文件uprobe符号信息 - collect_go_uprobe_syms_from_procfs(tps); - collect_ssl_uprobe_syms_from_procfs(tps); } /* ========================================================== @@ -748,17 +744,11 @@ static void process_event(struct process_event_t *e) if (e->maybe_thread && !is_user_process(e->pid)) return; update_proc_info_cache(e->pid, PROC_EXEC); - go_process_exec(e->pid); - ssl_process_exec(e->pid); - extended_process_exec(e->pid); unwind_process_exec(e->pid); } else if (e->meta.event_type == EVENT_TYPE_PROC_EXIT) { /* Cache for updating process information used in * symbol resolution. */ update_proc_info_cache(e->pid, PROC_EXIT); - go_process_exit(e->pid); - ssl_process_exit(e->pid); - extended_process_exit(e->pid); unwind_process_exit(e->pid); } } @@ -2119,10 +2109,7 @@ static void reconfig_load_resources(struct bpf_tracer *tracer, char *load_name, for (i = 0; i < tps->kfuncs_nr; i++) free(tps->kfuncs[i].name); tps->kfuncs_nr = 0; - if (g_k_type == K_TYPE_KFUNC) - config_probes_for_kfunc(tps); - else - config_probes_for_kprobe_and_tracepoint(tps); + socket_tracer_set_probes(tps); } /** @@ -2209,7 +2196,8 @@ int running_socket_tracer(tracer_callback_t handle, memset(tps, 0, sizeof(*tps)); init_list_head(&tps->uprobe_syms_head); socket_tracer_set_probes(tps); - + golang_trace_init(); + openssl_trace_init(); create_and_init_proc_info_caches(); struct bpf_tracer *tracer = @@ -2313,9 +2301,6 @@ int running_socket_tracer(tracer_callback_t handle, tracer->data_limit_max = socket_data_limit_max; - // Update go offsets to eBPF "proc_info_map" - update_proc_info_to_map(tracer); - // Insert prog of output data into map for using BPF Tail Calls. insert_output_prog_to_map(tracer); @@ -3146,3 +3131,11 @@ int disable_syscall_trace_id(void) ebpf_info("Disable tracing feature.\n"); return 0; } + +void uprobe_match_pid_handle(int feat, int pid, enum match_pids_act act) +{ + if (feat == FEATURE_UPROBE_GOLANG) + golang_trace_handle(pid, act); + else if (feat == FEATURE_UPROBE_OPENSSL) + openssl_trace_handle(pid, act); +} diff --git a/agent/src/ebpf/user/socket.h b/agent/src/ebpf/user/socket.h index e4b8c4b01cc..8db634656c7 100644 --- a/agent/src/ebpf/user/socket.h +++ b/agent/src/ebpf/user/socket.h @@ -415,4 +415,5 @@ int disable_syscall_trace_id(void); */ void config_probe(struct tracer_probes_conf *tps, int type, const char *fn, const char *tp_name, bool is_exit); +void uprobe_match_pid_handle(int feat, int pid, enum match_pids_act act); #endif /* DF_USER_SOCKET_H */ diff --git a/agent/src/ebpf/user/ssl_tracer.c b/agent/src/ebpf/user/ssl_tracer.c index 07ad73134d1..86880edb400 100644 --- a/agent/src/ebpf/user/ssl_tracer.c +++ b/agent/src/ebpf/user/ssl_tracer.c @@ -30,6 +30,7 @@ static proc_event_list_t proc_events; +/* *INDENT-OFF* */ static struct symbol symbols[] = { { .type = OPENSSL_UPROBE, @@ -56,6 +57,7 @@ static struct symbol symbols[] = { .is_probe_ret = true, }, }; +/* *INDENT-ON* */ static void openssl_parse_and_register(int pid, struct tracer_probes_conf *conf) { @@ -72,7 +74,8 @@ static void openssl_parse_and_register(int pid, struct tracer_probes_conf *conf) goto out; ebpf_info("openssl uprobe, pid:%d, path:%s\n", pid, path); - add_probe_sym_to_tracer_probes(pid, path, conf, symbols, NELEMS(symbols)); + add_probe_sym_to_tracer_probes(pid, path, conf, symbols, + NELEMS(symbols)); out: free(path); @@ -85,7 +88,7 @@ static void clear_ssl_probes_by_pid(struct bpf_tracer *tracer, int pid) struct list_head *p, *n; struct symbol_uprobe *sym_uprobe; - list_for_each_safe (p, n, &tracer->probes_head) { + list_for_each_safe(p, n, &tracer->probes_head) { probe = container_of(p, struct probe, list); if (!(probe->type == UPROBE && probe->private_data != NULL)) continue; @@ -116,13 +119,11 @@ int collect_ssl_uprobe_syms_from_procfs(struct tracer_probes_conf *conf) return ETR_OK; if (!kernel_version_check()) { - ebpf_warning("Uprobe openssl requires Linux version 4.17+ or Linux 3.10.0\n"); + ebpf_warning + ("Uprobe openssl requires Linux version 4.17+ or Linux 3.10.0\n"); return ETR_OK; } - init_list_head(&proc_events.head); - pthread_mutex_init(&proc_events.m, NULL); - fddir = opendir("/proc/"); if (!fddir) { ebpf_warning("Failed to open %s.\n"); @@ -163,9 +164,6 @@ void ssl_process_exec(int pid) if (tracer == NULL) return; - if (tracer->state != TRACER_RUNNING) - return; - if (tracer->probes_count > OPEN_FILES_MAX) { ebpf_warning("Probes count too many. The maximum is %d\n", OPEN_FILES_MAX); @@ -189,9 +187,6 @@ void ssl_process_exit(int pid) if (tracer == NULL) return; - if (tracer->state != TRACER_RUNNING) - return; - pthread_mutex_lock(&tracer->mutex_probes_lock); clear_ssl_probes_by_pid(tracer, pid); pthread_mutex_unlock(&tracer->mutex_probes_lock); @@ -210,6 +205,9 @@ void ssl_events_handle(void) if (get_sys_uptime() < event->expire_time) break; + if (event->stime != get_process_starttime(event->pid)) + goto next; + tracer = event->tracer; if (tracer) { pthread_mutex_lock(&tracer->mutex_probes_lock); @@ -219,8 +217,24 @@ void ssl_events_handle(void) pthread_mutex_unlock(&tracer->mutex_probes_lock); } + next: remove_event(&proc_events, event); free(event); } while (true); } + +void openssl_trace_handle(int pid, enum match_pids_act act) +{ + if (act == MATCH_PID_ADD) { + ssl_process_exec(pid); + } else { + ssl_process_exit(pid); + } +} + +void openssl_trace_init(void) +{ + init_list_head(&proc_events.head); + pthread_mutex_init(&proc_events.m, NULL); +} diff --git a/agent/src/ebpf/user/ssl_tracer.h b/agent/src/ebpf/user/ssl_tracer.h index e5c12b87a8a..31c4f92386d 100644 --- a/agent/src/ebpf/user/ssl_tracer.h +++ b/agent/src/ebpf/user/ssl_tracer.h @@ -30,5 +30,6 @@ void ssl_events_handle(void); // Process exit, reclaim resources void ssl_process_exit(int pid); - +void openssl_trace_handle(int pid, enum match_pids_act act); +void openssl_trace_init(void); #endif diff --git a/agent/src/ebpf/user/tracer.c b/agent/src/ebpf/user/tracer.c index ebc2a5ee33f..efc40999a6f 100644 --- a/agent/src/ebpf/user/tracer.c +++ b/agent/src/ebpf/user/tracer.c @@ -17,6 +17,7 @@ #define _GNU_SOURCE #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include "elf.h" #include "load.h" #include "mem.h" +#include "socket.h" #include "unwind_tracer.h" #include "extended/extended.h" @@ -115,7 +117,8 @@ struct match_pid_s { int *pids; int count; }; -static struct match_pid_s prev_match_pids[FEATURE_MAX]; +static struct match_pid_s last_match_pids[FEATURE_MAX]; +pthread_mutex_t match_pids_lock; // Used to store process IDs for matching various features pids_match_hash_t pids_match_hash; @@ -330,7 +333,8 @@ struct bpf_tracer *setup_bpf_tracer(const char *name, tracer_op_fun_t free_cb, tracer_op_fun_t create_cb, void *handle, - void *profiler_callback_ctx[PROFILER_CTX_NUM], + void + *profiler_callback_ctx[PROFILER_CTX_NUM], int sample_freq) { int ret; @@ -550,7 +554,8 @@ int tracer_bpf_load(struct bpf_tracer *tracer) if (ret != 0) { ebpf_warning("bpf load \"%s\" failed, error:%s (%d).\n", tracer->bpf_load_name, strerror(errno), errno); - if (!strcmp(tracer->bpf_load_name, "socket-trace-bpf-linux-kfunc")) { + if (!strcmp + (tracer->bpf_load_name, "socket-trace-bpf-linux-kfunc")) { ebpf_info("Try other eBPF bytecode binaries ...\n"); return ret; } @@ -999,9 +1004,9 @@ static int kfunc_detach(struct kfunc *p) int tracer_hooks_process(struct bpf_tracer *tracer, enum tracer_hook_type type, int *probes_count) { - int (*probe_handle) (struct probe *p) = NULL; - int (*tracepoint_handle) (struct tracepoint *p) = NULL; - int (*kfunc_handle) (struct kfunc *p) = NULL; + int (*probe_handle) (struct probe * p) = NULL; + int (*tracepoint_handle) (struct tracepoint * p) = NULL; + int (*kfunc_handle) (struct kfunc * p) = NULL; if (type == HOOK_ATTACH) { probe_handle = probe_attach; @@ -1130,18 +1135,21 @@ int tracer_hooks_process(struct bpf_tracer *tracer, enum tracer_hook_type type, if (obj->progs[i].type == BPF_PROG_TYPE_PERF_EVENT) { errno = 0; int ret = - program__attach_perf_event(obj-> - progs[i].prog_fd, + program__attach_perf_event(obj->progs[i]. + prog_fd, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 0, /* sample_period */ - tracer->sample_freq, + tracer-> + sample_freq, -1, /* pid, current process */ -1, /* cpu, no binding */ -1, /* new event group is created */ - tracer->per_cpu_fds, + tracer-> + per_cpu_fds, ARRAY_SIZE - (tracer->per_cpu_fds)); + (tracer-> + per_cpu_fds)); if (!ret) { ebpf_info ("tracer \"%s\" attach perf event prog successful.\n", @@ -1714,7 +1722,9 @@ int set_feature_regex(int feature, const char *pattern) cfg_feature_regex_array[feature].ok = true; - if (feature == FEATURE_PROFILE_ONCPU || feature == FEATURE_PROFILE_OFFCPU || feature == FEATURE_PROFILE_MEMORY) { + if (feature == FEATURE_PROFILE_ONCPU + || feature == FEATURE_PROFILE_OFFCPU + || feature == FEATURE_PROFILE_MEMORY) { unwind_process_reload(); } return 0; @@ -1722,18 +1732,21 @@ int set_feature_regex(int feature, const char *pattern) bool is_feature_enabled(int feature) { - if (feature < 0 || feature >= FEATURE_MAX) { - return false; - } + bool enabled = false; + pthread_mutex_lock(&match_pids_lock); + if (last_match_pids[feature].pids != NULL + && last_match_pids[feature].count > 0) + enabled = true; + pthread_mutex_unlock(&match_pids_lock); - return cfg_feature_regex_array[feature].ok; + return enabled; } bool is_feature_matched(int feature, int pid, const char *path) { if (pid > 0) return is_pid_match(feature, pid); - + int error = 0; char *path_for_basename = NULL; char *process_name = NULL; @@ -1769,9 +1782,8 @@ static int print_match_pids_kvp_cb(pids_match_hash_kv * kv, void *arg) { ebpf_info(" PID %lu flags 0x%lx (%s %s %s %s %s %s %s)\n", kv->key, kv->value, - (kv-> - value & (1 << FEATURE_UPROBE_GOLANG_SYMBOL)) ? "GOSYMBOL" : - "", + (kv->value & (1 << FEATURE_UPROBE_GOLANG_SYMBOL)) ? "GOSYMBOL" + : "", (kv->value & (1 << FEATURE_UPROBE_GOLANG)) ? "GOLANG" : "", (kv->value & (1 << FEATURE_UPROBE_OPENSSL)) ? "OPENSSL" : "", (kv->value & (1 << FEATURE_PROFILE_ONCPU)) ? "ONCPU" : "", @@ -1816,6 +1828,7 @@ static int add_pid_to_match_hash(int feature, int pid) ret = -1; } + uprobe_match_pid_handle(feature, pid, MATCH_PID_ADD); extended_match_pid_handle(feature, pid, MATCH_PID_ADD); return ret; } @@ -1850,6 +1863,7 @@ static int clear_pid_from_match_hash(int feature, int pid) } } + uprobe_match_pid_handle(feature, pid, MATCH_PID_DEL); extended_match_pid_handle(feature, pid, MATCH_PID_DEL); return ret; } @@ -1858,7 +1872,7 @@ static void del_stale_match_pids(int feature, const int *pids, int num) { int i, j; bool existed; - struct match_pid_s *prev_pids = &prev_match_pids[feature]; + struct match_pid_s *prev_pids = &last_match_pids[feature]; for (i = 0; i < prev_pids->count; i++) { existed = false; for (j = 0; j < num; j++) { @@ -1879,7 +1893,7 @@ static void add_new_match_pids(int feature, const int *pids, int num) { int i, j; bool existed; - struct match_pid_s *prev_pids = &prev_match_pids[feature]; + struct match_pid_s *prev_pids = &last_match_pids[feature]; for (i = 0; i < num; i++) { existed = false; for (j = 0; j < prev_pids->count; j++) { @@ -1896,11 +1910,54 @@ static void add_new_match_pids(int feature, const int *pids, int num) } } -int set_feature_pids(int feature, const int *pids, int num) +int exec_set_feature_pids(int feature, const int *pids, int num) +{ + del_stale_match_pids(feature, pids, num); + add_new_match_pids(feature, pids, num); + + pthread_mutex_lock(&match_pids_lock); + if (last_match_pids[feature].pids != NULL) { + free(last_match_pids[feature].pids); + last_match_pids[feature].pids = NULL; + last_match_pids[feature].count = 0; + } + + last_match_pids[feature].pids = malloc(sizeof(int) * num); + if (last_match_pids[feature].pids == NULL) { + ebpf_warning("last_match_pids[%d].pids malloc failed.\n", + feature); + pthread_mutex_unlock(&match_pids_lock); + return -1; + } + memcpy(last_match_pids[feature].pids, pids, sizeof(int) * num); + last_match_pids[feature].count = num; + pthread_mutex_unlock(&match_pids_lock); + return 0; +} + +int set_feature_pids(int feature, const int *match_pids, int num) { if (feature < 0 || feature >= FEATURE_MAX) { return -1; } + + int i, j = 0; + int pids[num]; + memset(pids, 0, sizeof(pids)); + for (i = 0; i < num; i++) { + //Check if the process exists + if (kill(match_pids[i], 0) == -1 && errno == ESRCH) { + ebpf_warning("The process with PID %d does not exist\n", + match_pids[i]); + } else if (!is_user_process(match_pids[i])) { + ebpf_warning("PID %d is not a user process.\n", + match_pids[i]); + } else { + pids[j++] = match_pids[i]; + } + } + + num = j; // Set the thread ID, which will be used in `pids_match_hash`. pthread_t tid = pthread_self(); struct thread_index_entry *v; @@ -1918,19 +1975,12 @@ int set_feature_pids(int feature, const int *pids, int num) ebpf_info("thread %ld index %ld\n", tid, thread_index); } - del_stale_match_pids(feature, pids, num); - add_new_match_pids(feature, pids, num); - - if (prev_match_pids[feature].pids != NULL) - free(prev_match_pids[feature].pids); - prev_match_pids[feature].pids = malloc(sizeof(int) * num); - memcpy(prev_match_pids[feature].pids, pids, sizeof(int) * num); - prev_match_pids[feature].count = num; - return 0; + return exec_set_feature_pids(feature, pids, num); } int init_match_pids_hash(void) { + pthread_mutex_init(&match_pids_lock, NULL); pids_match_hash_t *h = &pids_match_hash; memset(h, 0, sizeof(*h)); u32 nbuckets = PIDS_MATCH_HASH_BUCKETS_NUM; diff --git a/agent/src/ebpf/user/tracer.h b/agent/src/ebpf/user/tracer.h index 5cdc5b3f531..b2e4804d1db 100644 --- a/agent/src/ebpf/user/tracer.h +++ b/agent/src/ebpf/user/tracer.h @@ -700,7 +700,7 @@ int enable_tracer_reader_work(const char *name, int idx, * @return 0 on success, non-zero on error */ int enable_ebpf_seg_reasm_protocol(int protocol); - +int exec_set_feature_pids(int feature, const int *pids, int num); /** * @brief Add regex-matched process list for feature. *