diff --git a/src/fnargs.c b/src/fnargs.c index 67922ed..e1eeb9e 100644 --- a/src/fnargs.c +++ b/src/fnargs.c @@ -997,7 +997,7 @@ int prepare_ctx_args_specs(int probe_id, const struct inj_probe_info *inj) { struct ctx_args_info *ctx_args; char desc[256]; - int i, err; + int i, err = -EINVAL; snprintf_inj_probe(desc, sizeof(desc), inj); diff --git a/src/logic.c b/src/logic.c index 6d658da..73ef2b3 100644 --- a/src/logic.c +++ b/src/logic.c @@ -64,11 +64,11 @@ static void free_sessions(void) hashmap__clear(&sessions_hash); } -static void purge_session(struct ctx *ctx, int pid) +static void purge_session(struct ctx *ctx, int sess_id) { struct session *sess; - if (hashmap__delete(&sessions_hash, (long)pid, NULL, &sess)) + if (hashmap__delete(&sessions_hash, (long)sess_id, NULL, &sess)) free_session(sess); } @@ -76,14 +76,15 @@ static int handle_session_start(struct ctx *ctx, const struct rec_session_start { struct session *sess; - purge_session(ctx, r->pid); + purge_session(ctx, r->sess_id); sess = calloc(1, sizeof(*sess)); - if (!sess || hashmap__add(&sessions_hash, (long)r->pid, sess)) { - fprintf(stderr, "Failed to allocate memory for session PID %d!\n", r->pid); + if (!sess || hashmap__add(&sessions_hash, (long)r->sess_id, sess)) { + elog("Failed to allocate memory for session %d (PID %d)!\n", r->sess_id, r->pid); return -ENOMEM; } + sess->sess_id = r->sess_id; sess->pid = r->pid; sess->tgid = r->tgid; sess->start_ts = r->start_ts; @@ -96,7 +97,7 @@ static int handle_session_start(struct ctx *ctx, const struct rec_session_start static int handle_lbr_stack(struct ctx *dctx, struct session *sess, const struct rec_lbr_stack *r) { if (sess->lbrs) { - fprintf(stderr, "BUG: PID %d session data contains LBR data already!\n", r->pid); + elog("BUG: SESSION %d data contains LBR data already!\n", r->sess_id); return -EINVAL; } @@ -105,7 +106,7 @@ static int handle_lbr_stack(struct ctx *dctx, struct session *sess, const struct if (sess->lbrs_sz > 0) { sess->lbrs = malloc(sess->lbrs_sz); if (!sess->lbrs) { - fprintf(stderr, "SESSION PID %d: failed to allocate LBR memory: %d\n", r->pid, -ENOMEM); + elog("SESSION %d: failed to allocate LBR memory: %d\n", r->sess_id, -ENOMEM); return -ENOMEM; } memcpy(sess->lbrs, r->lbrs, sess->lbrs_sz); @@ -669,7 +670,7 @@ static struct func_args_item *find_fnargs_item(const struct session *sess, int s } static void prepare_trace_items(struct ctx *ctx, struct stack_items_cache *cache, - int pid, int last_seq_id) + int sess_id, int last_seq_id) { const struct mass_attacher_func_info *finfo; const struct inj_probe_info *inj; @@ -680,7 +681,7 @@ static void prepare_trace_items(struct ctx *ctx, struct stack_items_cache *cache int i, d, prev_seq_id = -1, orig_seq_id; int args_idx = 0, ctx_idx = 0; - if (!hashmap__find(&sessions_hash, (long)pid, &sess)) + if (!hashmap__find(&sessions_hash, (long)sess_id, &sess)) return; cache->cnt = 0; @@ -1260,9 +1261,10 @@ static int handle_session_end(struct ctx *dctx, struct session *sess, goto out_purge; if (env.debug) { - printf("GOT %s STACK (depth %u):\n", s->is_err ? "ERROR" : "SUCCESS", s->max_depth); + printf("SESSION %d GOT %s STACK (depth %u):\n", + sess->sess_id, s->is_err ? "ERROR" : "SUCCESS", s->max_depth); printf("DEPTH %d MAX DEPTH %d SAVED DEPTH %d MAX SAVED DEPTH %d\n", - s->depth, s->max_depth, s->saved_depth, s->saved_max_depth); + s->depth, s->max_depth, s->saved_depth, s->saved_max_depth); } ts_to_str(ktime_to_ts(sess->start_ts), ts1, sizeof(ts1)); @@ -1279,7 +1281,7 @@ static int handle_session_end(struct ctx *dctx, struct session *sess, * call stack trace (depth == 0) */ if (env.emit_func_trace && s->depth == 0) { - prepare_trace_items(dctx, &stack_items1, sess->pid, r->last_seq_id); + prepare_trace_items(dctx, &stack_items1, sess->sess_id, r->last_seq_id); print_trace_items(dctx, &stack_items1); } @@ -1336,7 +1338,7 @@ static int handle_session_end(struct ctx *dctx, struct session *sess, printf("\n\n"); out_purge: - purge_session(dctx, r->pid); + purge_session(dctx, r->sess_id); return ret; } @@ -1361,8 +1363,8 @@ int handle_event(void *ctx, void *data, size_t data_sz) case REC_FUNC_TRACE_EXIT: { const struct rec_func_trace_entry *r = data; - if (!hashmap__find(&sessions_hash, (long)r->pid, &sess)) { - fprintf(stderr, "BUG: PID %d session data not found (%s)!\n", r->pid, + if (!hashmap__find(&sessions_hash, (long)r->sess_id, &sess)) { + fprintf(stderr, "BUG: Session %d data not found (%s)!\n", r->sess_id, r->type == REC_FUNC_TRACE_ENTRY ? "FUNC_TRACE_ENTRY" : "FUNC_TRACE_EXIT"); return -EINVAL; } @@ -1371,8 +1373,8 @@ int handle_event(void *ctx, void *data, size_t data_sz) case REC_FNARGS_CAPTURE: { struct rec_fnargs_capture *r = data; - if (!hashmap__find(&sessions_hash, (long)r->pid, &sess)) { - fprintf(stderr, "BUG: PID %d session data not found (FUNC_ARGS_CAPTURE)!\n", r->pid); + if (!hashmap__find(&sessions_hash, (long)r->sess_id, &sess)) { + fprintf(stderr, "BUG: SESSION %d session data not found (FUNC_ARGS_CAPTURE)!\n", r->sess_id); return -EINVAL; } return handle_fnargs_capture(ctx, sess, r); @@ -1380,8 +1382,8 @@ int handle_event(void *ctx, void *data, size_t data_sz) case REC_LBR_STACK: { const struct rec_lbr_stack *r = data; - if (!hashmap__find(&sessions_hash, (long)r->pid, &sess)) { - fprintf(stderr, "BUG: PID %d session data not found (LBR_STACK)!\n", r->pid); + if (!hashmap__find(&sessions_hash, (long)r->sess_id, &sess)) { + fprintf(stderr, "BUG: SESSION %d session data not found (LBR_STACK)!\n", r->sess_id); return -EINVAL; } return handle_lbr_stack(ctx, sess, r); @@ -1389,8 +1391,8 @@ int handle_event(void *ctx, void *data, size_t data_sz) case REC_INJ_PROBE: { const struct rec_inj_probe *r = data; - if (!hashmap__find(&sessions_hash, (long)r->pid, &sess)) { - fprintf(stderr, "BUG: PID %d session data not found (INJ_PROBE)!\n", r->pid); + if (!hashmap__find(&sessions_hash, (long)r->sess_id, &sess)) { + fprintf(stderr, "BUG: SESSION %d session data not found (INJ_PROBE)!\n", r->sess_id); return -EINVAL; } return handle_inj_probe(ctx, sess, r); @@ -1398,8 +1400,8 @@ int handle_event(void *ctx, void *data, size_t data_sz) case REC_CTXARGS_CAPTURE: { const struct rec_ctxargs_capture *r = data; - if (!hashmap__find(&sessions_hash, (long)r->pid, &sess)) { - fprintf(stderr, "BUG: PID %d session data not found (CTX_CAPTURE)!\n", r->pid); + if (!hashmap__find(&sessions_hash, (long)r->sess_id, &sess)) { + fprintf(stderr, "BUG: SESSION %d session data not found (CTX_CAPTURE)!\n", r->sess_id); return -EINVAL; } return handle_ctx_capture(ctx, sess, r); @@ -1407,8 +1409,8 @@ int handle_event(void *ctx, void *data, size_t data_sz) case REC_SESSION_END: { const struct rec_session_end *r = data; - if (!hashmap__find(&sessions_hash, (long)r->pid, &sess)) { - fprintf(stderr, "BUG: PID %d session data not found (SESSION_END)!\n", r->pid); + if (!hashmap__find(&sessions_hash, (long)r->sess_id, &sess)) { + fprintf(stderr, "BUG: SESSION %d session data not found (SESSION_END)!\n", r->sess_id); return -EINVAL; } return handle_session_end(ctx, sess, r); diff --git a/src/logic.h b/src/logic.h index bd0c7b3..acd1dcb 100644 --- a/src/logic.h +++ b/src/logic.h @@ -47,6 +47,7 @@ struct trace_item { }; struct session { + int sess_id; int pid; int tgid; uint64_t start_ts; diff --git a/src/retsnoop.bpf.c b/src/retsnoop.bpf.c index 3889db4..ea3c297 100644 --- a/src/retsnoop.bpf.c +++ b/src/retsnoop.bpf.c @@ -40,6 +40,7 @@ static inline void atomic_add(long *value, long n) } struct session { + int sess_id; int pid, tgid; long start_ts; char task_comm[16], proc_comm[16]; @@ -321,7 +322,7 @@ static __noinline void record_fnargs(void *ctx, struct session *sess, u32 func_i } r->type = REC_FNARGS_CAPTURE; - r->pid = sess->pid; + r->sess_id = sess->sess_id; r->seq_id = seq_id; r->func_id = func_id; r->arg_ptrs = 0; @@ -417,7 +418,7 @@ static __noinline void record_ctxargs(void *ctx, struct session *sess, u32 probe } r->type = REC_CTXARGS_CAPTURE; - r->pid = sess->pid; + r->sess_id = sess->sess_id; r->seq_id = seq_id; r->probe_id = probe_id; r->ptrs_mask = 0; @@ -542,6 +543,7 @@ static bool emit_session_start(struct session *sess) } r->type = REC_SESSION_START; + r->sess_id = sess->sess_id; r->pid = sess->pid; r->tgid = sess->tgid; r->start_ts = sess->start_ts; @@ -553,28 +555,35 @@ static bool emit_session_start(struct session *sess) return true; } +static __always_inline int session_id(int pid) +{ + return pid ?: -(1 + bpf_get_smp_processor_id()); +} + static __noinline bool push_call_stack(void *ctx, u32 id, u64 ip) { u64 pid_tgid = bpf_get_current_pid_tgid(); u32 pid = (u32)pid_tgid; struct session *sess; - int seq_id; + int seq_id, sess_id; u64 d; - sess = bpf_map_lookup_elem(&sessions, &pid); + sess_id = session_id(pid); + sess = bpf_map_lookup_elem(&sessions, &sess_id); if (!sess) { struct task_struct *tsk; if (!(func_info(id)->flags & FUNC_IS_ENTRY)) return false; - bpf_map_update_elem(&sessions, &pid, &empty_session, BPF_ANY); - sess = bpf_map_lookup_elem(&sessions, &pid); + bpf_map_update_elem(&sessions, &sess_id, &empty_session, BPF_ANY); + sess = bpf_map_lookup_elem(&sessions, &sess_id); if (!sess) { atomic_inc(&stats.dropped_sessions); return false; } + sess->sess_id = sess_id; sess->pid = pid; sess->tgid = (u32)(pid_tgid >> 32); sess->start_ts = bpf_ktime_get_ns(); @@ -584,8 +593,8 @@ static __noinline bool push_call_stack(void *ctx, u32 id, u64 ip) if (emit_func_trace || capture_args) { if (!emit_session_start(sess)) { - vlog("DEFUNCT SESSION TID/PID %d/%d: failed to send SESSION_START record!\n", - sess->pid, sess->tgid); + vlog("DEFUNCT SESSION %d TID/PID %d/%d: failed to send SESSION_START record!\n", + sess->sess_id, sess->pid, sess->tgid); sess->defunct = true; goto out_defunct; } else { @@ -630,7 +639,7 @@ static __noinline bool push_call_stack(void *ctx, u32 id, u64 ip) fe->type = REC_FUNC_TRACE_ENTRY; fe->ts = bpf_ktime_get_ns(); - fe->pid = pid; + fe->sess_id = sess_id; fe->seq_id = seq_id; fe->depth = d + 1; fe->func_id = id; @@ -649,13 +658,13 @@ skip_ft_entry:; if (printk_is_sane) { if (d == 0) - log("=== STARTING TRACING %s [COMM %s PID %d] ===", - func_name, sess->task_comm, pid); + log("=== STARTING TRACING %s [COMM %s SESS %d] ===", + func_name, sess->task_comm, sess_id); log(" ENTER %s%s [...]", spaces + 2 * ((255 - d) & 0xFF), func_name); } else { if (d == 0) { - log("=== STARTING TRACING %s [PID %d] ===", func_name, pid); - log("=== ... TRACING [PID %d COMM %s] ===", pid, sess->task_comm); + log("=== STARTING TRACING %s [SESS %d] ===", func_name, sess_id); + log("=== ... TRACING [SESS %d COMM %s] ===", sess_id, sess->task_comm); } log(" ENTER [%d] %s [...]", d + 1, func_name); } @@ -826,8 +835,8 @@ static int submit_session(void *ctx, struct session *sess) if (emit_session && !sess->start_emitted) { if (!emit_session_start(sess)) { - vlog("DEFUNCT SESSION TID/PID %d/%d: failed to send SESSION data!\n", - sess->pid, sess->tgid); + vlog("DEFUNCT SESSION %d TID/PID %d/%d: failed to send SESSION data!\n", + sess->sess_id, sess->pid, sess->tgid); sess->defunct = true; return -EINVAL; } @@ -849,7 +858,7 @@ static int submit_session(void *ctx, struct session *sess) } r->type = REC_LBR_STACK; - r->pid = sess->pid; + r->sess_id = sess->sess_id; r->lbrs_sz = sess->lbrs_sz; __memcpy(r->lbrs, sess->lbrs, sizeof(sess->lbrs)); @@ -867,7 +876,7 @@ skip_lbrs:; } r->type = REC_SESSION_END; - r->pid = sess->pid; + r->sess_id = sess->sess_id; r->emit_ts = emit_ts; r->ignored = !emit_session; r->is_err = sess->stack.is_err; @@ -894,10 +903,11 @@ static __noinline bool pop_call_stack(void *ctx, u32 id, u64 ip, long res) const char *fmt; bool failed; u64 d, lat; - int seq_id; + int seq_id, sess_id; pid = (u32)bpf_get_current_pid_tgid(); - sess = bpf_map_lookup_elem(&sessions, &pid); + sess_id = session_id(pid); + sess = bpf_map_lookup_elem(&sessions, &sess_id); if (!sess) return false; @@ -906,9 +916,9 @@ static __noinline bool pop_call_stack(void *ctx, u32 id, u64 ip, long res) sess->stack.depth--; if (sess->stack.depth == 0) { reset_session(sess); - bpf_map_delete_elem(&sessions, &pid); - vlog("DEFUNCT SESSION TID/PID %d/%d: SESSION_END, no data was collected!\n", - pid, sess->tgid); + bpf_map_delete_elem(&sessions, &sess_id); + vlog("DEFUNCT SESSION %d TID/PID %d/%d: SESSION_END, no data was collected!\n", + sess_id, pid, sess->tgid); } return false; } @@ -960,7 +970,7 @@ static __noinline bool pop_call_stack(void *ctx, u32 id, u64 ip, long res) fe->type = REC_FUNC_TRACE_EXIT; fe->ts = bpf_ktime_get_ns(); - fe->pid = pid; + fe->sess_id = sess_id; fe->seq_id = seq_id; fe->depth = d + 1; fe->func_id = id; @@ -986,7 +996,7 @@ skip_ft_exit:; atomic_inc(&stats.dropped_sessions); reset_session(sess); - bpf_map_delete_elem(&sessions, &pid); + bpf_map_delete_elem(&sessions, &sess_id); return false; } @@ -1011,7 +1021,7 @@ skip_ft_exit:; submit_session(ctx, sess); reset_session(sess); - bpf_map_delete_elem(&sessions, &pid); + bpf_map_delete_elem(&sessions, &sess_id); } return true; @@ -1020,11 +1030,12 @@ skip_ft_exit:; static void handle_inj_probe(void *ctx, u32 id) { struct session *sess; - int seq_id, err; + int seq_id, sess_id, err; u32 pid; pid = (u32)bpf_get_current_pid_tgid(); - sess = bpf_map_lookup_elem(&sessions, &pid); + sess_id = session_id(pid); + sess = bpf_map_lookup_elem(&sessions, &sess_id); if (!sess || sess->defunct) return; @@ -1042,7 +1053,7 @@ static void handle_inj_probe(void *ctx, u32 id) r->type = REC_INJ_PROBE; r->ts = bpf_ktime_get_ns(); - r->pid = pid; + r->sess_id = sess_id; r->seq_id = seq_id; r->probe_id = id; r->depth = sess->stack.depth + 1; diff --git a/src/retsnoop.h b/src/retsnoop.h index 318e1c7..a3b7663 100644 --- a/src/retsnoop.h +++ b/src/retsnoop.h @@ -130,6 +130,7 @@ struct ctxargs_info { struct rec_session_start { /* REC_SESSION_START */ enum rec_type type; + int sess_id; int pid; int tgid; long start_ts; @@ -140,7 +141,7 @@ struct rec_func_trace_entry { /* REC_FUNC_TRACE_ENTRY or REC_FUNC_TRACE_EXIT */ enum rec_type type; - int pid; + int sess_id; long ts; int seq_id; @@ -154,7 +155,7 @@ struct rec_func_trace_entry { struct rec_fnargs_capture { /* REC_FNARGS_CAPTURE */ enum rec_type type; - int pid; + int sess_id; int seq_id; unsigned short func_id; unsigned short data_len; @@ -166,7 +167,7 @@ struct rec_fnargs_capture { struct rec_ctxargs_capture { /* REC_CTXARGS_CAPTURE */ enum rec_type type; - int pid; + int sess_id; int seq_id; unsigned short probe_id; unsigned short data_len; @@ -178,7 +179,7 @@ struct rec_ctxargs_capture { struct rec_lbr_stack { /* REC_LBR_STACK */ enum rec_type type; - int pid; + int sess_id; int lbrs_sz; struct perf_branch_entry lbrs[MAX_LBR_ENTRIES]; @@ -187,7 +188,7 @@ struct rec_lbr_stack { struct rec_inj_probe { /* REC_INJ_PROBE */ enum rec_type type; - int pid; + int sess_id; long ts; int seq_id; @@ -224,7 +225,7 @@ struct call_stack { struct rec_session_end { /* REC_SESSION_END */ enum rec_type type; - int pid; + int sess_id; long emit_ts; bool ignored; bool is_err;