@@ -210,13 +210,12 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
210210}
211211
212212static struct perf_callchain_entry *
213- get_callchain_entry_for_task (struct task_struct * task , u32 max_depth )
213+ get_callchain_entry_for_task (int * rctx , struct task_struct * task , u32 max_depth )
214214{
215215#ifdef CONFIG_STACKTRACE
216216 struct perf_callchain_entry * entry ;
217- int rctx ;
218217
219- entry = get_callchain_entry (& rctx );
218+ entry = get_callchain_entry (rctx );
220219
221220 if (!entry )
222221 return NULL ;
@@ -238,8 +237,6 @@ get_callchain_entry_for_task(struct task_struct *task, u32 max_depth)
238237 to [i ] = (u64 )(from [i ]);
239238 }
240239
241- put_callchain_entry (rctx );
242-
243240 return entry ;
244241#else /* CONFIG_STACKTRACE */
245242 return NULL ;
@@ -320,6 +317,31 @@ static long __bpf_get_stackid(struct bpf_map *map,
320317 return id ;
321318}
322319
320+ static struct perf_callchain_entry *
321+ bpf_get_perf_callchain (int * rctx , struct pt_regs * regs , bool kernel , bool user ,
322+ int max_stack , bool crosstask )
323+ {
324+ struct perf_callchain_entry_ctx ctx ;
325+ struct perf_callchain_entry * entry ;
326+
327+ entry = get_callchain_entry (rctx );
328+ if (unlikely (!entry ))
329+ return NULL ;
330+
331+ __init_perf_callchain_ctx (& ctx , entry , max_stack , false);
332+ if (kernel )
333+ __get_perf_callchain_kernel (& ctx , regs );
334+ if (user && !crosstask )
335+ __get_perf_callchain_user (& ctx , regs );
336+
337+ return entry ;
338+ }
339+
340+ static void bpf_put_perf_callchain (int rctx )
341+ {
342+ put_callchain_entry (rctx );
343+ }
344+
323345BPF_CALL_3 (bpf_get_stackid , struct pt_regs * , regs , struct bpf_map * , map ,
324346 u64 , flags )
325347{
@@ -328,20 +350,24 @@ BPF_CALL_3(bpf_get_stackid, struct pt_regs *, regs, struct bpf_map *, map,
328350 struct perf_callchain_entry * trace ;
329351 bool kernel = !user ;
330352 u32 max_depth ;
353+ int rctx , ret ;
331354
332355 if (unlikely (flags & ~(BPF_F_SKIP_FIELD_MASK | BPF_F_USER_STACK |
333356 BPF_F_FAST_STACK_CMP | BPF_F_REUSE_STACKID )))
334357 return - EINVAL ;
335358
336359 max_depth = stack_map_calculate_max_depth (map -> value_size , elem_size , flags );
337- trace = get_perf_callchain ( regs , kernel , user , max_depth ,
338- false, false);
360+ trace = bpf_get_perf_callchain ( & rctx , regs , kernel , user , max_depth ,
361+ false);
339362
340363 if (unlikely (!trace ))
341364 /* couldn't fetch the stack trace */
342365 return - EFAULT ;
343366
344- return __bpf_get_stackid (map , trace , flags );
367+ ret = __bpf_get_stackid (map , trace , flags );
368+ bpf_put_perf_callchain (rctx );
369+
370+ return ret ;
345371}
346372
347373const struct bpf_func_proto bpf_get_stackid_proto = {
@@ -435,6 +461,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
435461 bool kernel = !user ;
436462 int err = - EINVAL ;
437463 u64 * ips ;
464+ int rctx ;
438465
439466 if (unlikely (flags & ~(BPF_F_SKIP_FIELD_MASK | BPF_F_USER_STACK |
440467 BPF_F_USER_BUILD_ID )))
@@ -467,18 +494,26 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
467494 trace = trace_in ;
468495 trace -> nr = min_t (u32 , trace -> nr , max_depth );
469496 } else if (kernel && task ) {
470- trace = get_callchain_entry_for_task (task , max_depth );
497+ trace = get_callchain_entry_for_task (& rctx , task , max_depth );
471498 } else {
472- trace = get_perf_callchain ( regs , kernel , user , max_depth ,
473- crosstask , false );
499+ trace = bpf_get_perf_callchain ( & rctx , regs , kernel , user , max_depth ,
500+ crosstask );
474501 }
475502
476- if (unlikely (!trace ) || trace -> nr < skip ) {
503+ if (unlikely (!trace )) {
477504 if (may_fault )
478505 rcu_read_unlock ();
479506 goto err_fault ;
480507 }
481508
509+ if (trace -> nr < skip ) {
510+ if (may_fault )
511+ rcu_read_unlock ();
512+ if (!trace_in )
513+ bpf_put_perf_callchain (rctx );
514+ goto err_fault ;
515+ }
516+
482517 trace_nr = trace -> nr - skip ;
483518 copy_len = trace_nr * elem_size ;
484519
@@ -497,6 +532,9 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
497532 if (may_fault )
498533 rcu_read_unlock ();
499534
535+ if (!trace_in )
536+ bpf_put_perf_callchain (rctx );
537+
500538 if (user_build_id )
501539 stack_map_get_build_id_offset (buf , trace_nr , user , may_fault );
502540
0 commit comments