Skip to content

Commit 9b99edc

Browse files
Jiri OlsaAlexei Starovoitov
authored andcommitted
bpf: Add bpf_get_func_ip helper for tracing programs
Adding bpf_get_func_ip helper for BPF_PROG_TYPE_TRACING programs, specifically for all trampoline attach types. The trampoline's caller IP address is stored in (ctx - 8) address. so there's no reason to actually call the helper, but rather fixup the call instruction and return [ctx - 8] value directly. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20210714094400.396467-4-jolsa@kernel.org
1 parent 1e37392 commit 9b99edc

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

include/uapi/linux/bpf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4841,6 +4841,12 @@ union bpf_attr {
48414841
* **-EINVAL** if *timer* was not initialized with bpf_timer_init() earlier.
48424842
* **-EDEADLK** if callback_fn tried to call bpf_timer_cancel() on its
48434843
* own timer which would have led to a deadlock otherwise.
4844+
*
4845+
* u64 bpf_get_func_ip(void *ctx)
4846+
* Description
4847+
* Get address of the traced function (for tracing programs).
4848+
* Return
4849+
* Address of the traced function.
48444850
*/
48454851
#define __BPF_FUNC_MAPPER(FN) \
48464852
FN(unspec), \
@@ -5016,6 +5022,7 @@ union bpf_attr {
50165022
FN(timer_set_callback), \
50175023
FN(timer_start), \
50185024
FN(timer_cancel), \
5025+
FN(get_func_ip), \
50195026
/* */
50205027

50215028
/* integer value in 'imm' field of BPF_CALL instruction selects which helper

kernel/bpf/verifier.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6161,6 +6161,27 @@ static int check_bpf_snprintf_call(struct bpf_verifier_env *env,
61616161
return err;
61626162
}
61636163

6164+
static int check_get_func_ip(struct bpf_verifier_env *env)
6165+
{
6166+
enum bpf_attach_type eatype = env->prog->expected_attach_type;
6167+
enum bpf_prog_type type = resolve_prog_type(env->prog);
6168+
int func_id = BPF_FUNC_get_func_ip;
6169+
6170+
if (type == BPF_PROG_TYPE_TRACING) {
6171+
if (eatype != BPF_TRACE_FENTRY && eatype != BPF_TRACE_FEXIT &&
6172+
eatype != BPF_MODIFY_RETURN) {
6173+
verbose(env, "func %s#%d supported only for fentry/fexit/fmod_ret programs\n",
6174+
func_id_name(func_id), func_id);
6175+
return -ENOTSUPP;
6176+
}
6177+
return 0;
6178+
}
6179+
6180+
verbose(env, "func %s#%d not supported for program type %d\n",
6181+
func_id_name(func_id), func_id, type);
6182+
return -ENOTSUPP;
6183+
}
6184+
61646185
static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
61656186
int *insn_idx_p)
61666187
{
@@ -6439,6 +6460,12 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
64396460
if (func_id == BPF_FUNC_get_stackid || func_id == BPF_FUNC_get_stack)
64406461
env->prog->call_get_stack = true;
64416462

6463+
if (func_id == BPF_FUNC_get_func_ip) {
6464+
if (check_get_func_ip(env))
6465+
return -ENOTSUPP;
6466+
env->prog->call_get_func_ip = true;
6467+
}
6468+
64426469
if (changes_data)
64436470
clear_all_pkt_pointers(env);
64446471
return 0;
@@ -12632,6 +12659,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1263212659
{
1263312660
struct bpf_prog *prog = env->prog;
1263412661
bool expect_blinding = bpf_jit_blinding_enabled(prog);
12662+
enum bpf_prog_type prog_type = resolve_prog_type(prog);
1263512663
struct bpf_insn *insn = prog->insnsi;
1263612664
const struct bpf_func_proto *fn;
1263712665
const int insn_cnt = prog->len;
@@ -12998,6 +13026,21 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1299813026
continue;
1299913027
}
1300013028

13029+
/* Implement bpf_get_func_ip inline. */
13030+
if (prog_type == BPF_PROG_TYPE_TRACING &&
13031+
insn->imm == BPF_FUNC_get_func_ip) {
13032+
/* Load IP address from ctx - 8 */
13033+
insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
13034+
13035+
new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, 1);
13036+
if (!new_prog)
13037+
return -ENOMEM;
13038+
13039+
env->prog = prog = new_prog;
13040+
insn = new_prog->insnsi + i + delta;
13041+
continue;
13042+
}
13043+
1300113044
patch_call_imm:
1300213045
fn = env->ops->get_func_proto(insn->imm, env->prog);
1300313046
/* all functions that have prototype and verifier allowed

kernel/trace/bpf_trace.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,19 @@ const struct bpf_func_proto bpf_snprintf_btf_proto = {
948948
.arg5_type = ARG_ANYTHING,
949949
};
950950

951+
BPF_CALL_1(bpf_get_func_ip_tracing, void *, ctx)
952+
{
953+
/* This helper call is inlined by verifier. */
954+
return ((u64 *)ctx)[-1];
955+
}
956+
957+
static const struct bpf_func_proto bpf_get_func_ip_proto_tracing = {
958+
.func = bpf_get_func_ip_tracing,
959+
.gpl_only = true,
960+
.ret_type = RET_INTEGER,
961+
.arg1_type = ARG_PTR_TO_CTX,
962+
};
963+
951964
const struct bpf_func_proto *
952965
bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
953966
{
@@ -1058,6 +1071,8 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
10581071
return &bpf_for_each_map_elem_proto;
10591072
case BPF_FUNC_snprintf:
10601073
return &bpf_snprintf_proto;
1074+
case BPF_FUNC_get_func_ip:
1075+
return &bpf_get_func_ip_proto_tracing;
10611076
default:
10621077
return bpf_base_func_proto(func_id);
10631078
}

tools/include/uapi/linux/bpf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4841,6 +4841,12 @@ union bpf_attr {
48414841
* **-EINVAL** if *timer* was not initialized with bpf_timer_init() earlier.
48424842
* **-EDEADLK** if callback_fn tried to call bpf_timer_cancel() on its
48434843
* own timer which would have led to a deadlock otherwise.
4844+
*
4845+
* u64 bpf_get_func_ip(void *ctx)
4846+
* Description
4847+
* Get address of the traced function (for tracing programs).
4848+
* Return
4849+
* Address of the traced function.
48444850
*/
48454851
#define __BPF_FUNC_MAPPER(FN) \
48464852
FN(unspec), \
@@ -5016,6 +5022,7 @@ union bpf_attr {
50165022
FN(timer_set_callback), \
50175023
FN(timer_start), \
50185024
FN(timer_cancel), \
5025+
FN(get_func_ip), \
50195026
/* */
50205027

50215028
/* integer value in 'imm' field of BPF_CALL instruction selects which helper

0 commit comments

Comments
 (0)