Message ID | 20201103153132.2717326-5-kpsingh@chromium.org (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | Implement task_local_storage | expand |
> On Nov 3, 2020, at 7:31 AM, KP Singh <kpsingh@chromium.org> wrote: > > From: KP Singh <kpsingh@google.com> > > The currently available bpf_get_current_task returns an unsigned integer > which can be used along with BPF_CORE_READ to read data from > the task_struct but still cannot be used as an input argument to a > helper that accepts an ARG_PTR_TO_BTF_ID of type task_struct. > > In order to implement this helper a new return type, RET_PTR_TO_BTF_ID, > is added. This is similar to RET_PTR_TO_BTF_ID_OR_NULL but does not > require checking the nullness of returned pointer. > > Signed-off-by: KP Singh <kpsingh@google.com> Acked-by: Song Liu <songliubraving@fb.com> > --- > include/linux/bpf.h | 1 + > include/uapi/linux/bpf.h | 9 +++++++++ > kernel/bpf/verifier.c | 7 +++++-- > kernel/trace/bpf_trace.c | 16 ++++++++++++++++ > tools/include/uapi/linux/bpf.h | 9 +++++++++ > 5 files changed, 40 insertions(+), 2 deletions(-) > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index 2fffd30e13ac..73d5381a5d5c 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -310,6 +310,7 @@ enum bpf_return_type { > RET_PTR_TO_BTF_ID_OR_NULL, /* returns a pointer to a btf_id or NULL */ > RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, /* returns a pointer to a valid memory or a btf_id or NULL */ > RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */ > + RET_PTR_TO_BTF_ID, /* returns a pointer to a btf_id */ > }; > > /* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h > index f4037b2161a6..9879d6793e90 100644 > --- a/include/uapi/linux/bpf.h > +++ b/include/uapi/linux/bpf.h > @@ -3779,6 +3779,14 @@ union bpf_attr { > * 0 on success. > * > * **-ENOENT** if the bpf_local_storage cannot be found. > + * > + * struct task_struct *bpf_get_current_task_btf(void) > + * Description > + * Return a BTF pointer to the "current" task. > + * This pointer can also be used in helpers that accept an > + * *ARG_PTR_TO_BTF_ID* of type *task_struct*. > + * Return > + * Pointer to the current task. > */ > #define __BPF_FUNC_MAPPER(FN) \ > FN(unspec), \ > @@ -3939,6 +3947,7 @@ union bpf_attr { > FN(redirect_peer), \ > FN(task_storage_get), \ > FN(task_storage_delete), \ > + FN(get_current_task_btf), \ > /* */ > > /* integer value in 'imm' field of BPF_CALL instruction selects which helper > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index b0790876694f..314018e8fc12 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c > @@ -5186,11 +5186,14 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn > PTR_TO_BTF_ID : PTR_TO_BTF_ID_OR_NULL; > regs[BPF_REG_0].btf_id = meta.ret_btf_id; > } > - } else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL) { > + } else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL || > + fn->ret_type == RET_PTR_TO_BTF_ID) { > int ret_btf_id; > > mark_reg_known_zero(env, regs, BPF_REG_0); > - regs[BPF_REG_0].type = PTR_TO_BTF_ID_OR_NULL; > + regs[BPF_REG_0].type = fn->ret_type == RET_PTR_TO_BTF_ID ? > + PTR_TO_BTF_ID : > + PTR_TO_BTF_ID_OR_NULL; > ret_btf_id = *fn->ret_btf_id; > if (ret_btf_id == 0) { > verbose(env, "invalid return type %d of func %s#%d\n", > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c > index 4517c8b66518..e4515b0f62a8 100644 > --- a/kernel/trace/bpf_trace.c > +++ b/kernel/trace/bpf_trace.c > @@ -1022,6 +1022,20 @@ const struct bpf_func_proto bpf_get_current_task_proto = { > .ret_type = RET_INTEGER, > }; > > +BPF_CALL_0(bpf_get_current_task_btf) > +{ > + return (unsigned long) current; > +} > + > +BTF_ID_LIST_SINGLE(bpf_get_current_btf_ids, struct, task_struct) > + > +static const struct bpf_func_proto bpf_get_current_task_btf_proto = { > + .func = bpf_get_current_task_btf, > + .gpl_only = true, > + .ret_type = RET_PTR_TO_BTF_ID, > + .ret_btf_id = &bpf_get_current_btf_ids[0], > +}; > + > BPF_CALL_2(bpf_current_task_under_cgroup, struct bpf_map *, map, u32, idx) > { > struct bpf_array *array = container_of(map, struct bpf_array, map); > @@ -1265,6 +1279,8 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) > return &bpf_get_current_pid_tgid_proto; > case BPF_FUNC_get_current_task: > return &bpf_get_current_task_proto; > + case BPF_FUNC_get_current_task_btf: > + return &bpf_get_current_task_btf_proto; > case BPF_FUNC_get_current_uid_gid: > return &bpf_get_current_uid_gid_proto; > case BPF_FUNC_get_current_comm: > diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h > index f4037b2161a6..9879d6793e90 100644 > --- a/tools/include/uapi/linux/bpf.h > +++ b/tools/include/uapi/linux/bpf.h > @@ -3779,6 +3779,14 @@ union bpf_attr { > * 0 on success. > * > * **-ENOENT** if the bpf_local_storage cannot be found. > + * > + * struct task_struct *bpf_get_current_task_btf(void) > + * Description > + * Return a BTF pointer to the "current" task. > + * This pointer can also be used in helpers that accept an > + * *ARG_PTR_TO_BTF_ID* of type *task_struct*. > + * Return > + * Pointer to the current task. > */ > #define __BPF_FUNC_MAPPER(FN) \ > FN(unspec), \ > @@ -3939,6 +3947,7 @@ union bpf_attr { > FN(redirect_peer), \ > FN(task_storage_get), \ > FN(task_storage_delete), \ > + FN(get_current_task_btf), \ > /* */ > > /* integer value in 'imm' field of BPF_CALL instruction selects which helper > -- > 2.29.1.341.ge80a0c044ae-goog >
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 2fffd30e13ac..73d5381a5d5c 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -310,6 +310,7 @@ enum bpf_return_type { RET_PTR_TO_BTF_ID_OR_NULL, /* returns a pointer to a btf_id or NULL */ RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, /* returns a pointer to a valid memory or a btf_id or NULL */ RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */ + RET_PTR_TO_BTF_ID, /* returns a pointer to a btf_id */ }; /* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index f4037b2161a6..9879d6793e90 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -3779,6 +3779,14 @@ union bpf_attr { * 0 on success. * * **-ENOENT** if the bpf_local_storage cannot be found. + * + * struct task_struct *bpf_get_current_task_btf(void) + * Description + * Return a BTF pointer to the "current" task. + * This pointer can also be used in helpers that accept an + * *ARG_PTR_TO_BTF_ID* of type *task_struct*. + * Return + * Pointer to the current task. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -3939,6 +3947,7 @@ union bpf_attr { FN(redirect_peer), \ FN(task_storage_get), \ FN(task_storage_delete), \ + FN(get_current_task_btf), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index b0790876694f..314018e8fc12 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5186,11 +5186,14 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn PTR_TO_BTF_ID : PTR_TO_BTF_ID_OR_NULL; regs[BPF_REG_0].btf_id = meta.ret_btf_id; } - } else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL) { + } else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL || + fn->ret_type == RET_PTR_TO_BTF_ID) { int ret_btf_id; mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = PTR_TO_BTF_ID_OR_NULL; + regs[BPF_REG_0].type = fn->ret_type == RET_PTR_TO_BTF_ID ? + PTR_TO_BTF_ID : + PTR_TO_BTF_ID_OR_NULL; ret_btf_id = *fn->ret_btf_id; if (ret_btf_id == 0) { verbose(env, "invalid return type %d of func %s#%d\n", diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 4517c8b66518..e4515b0f62a8 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1022,6 +1022,20 @@ const struct bpf_func_proto bpf_get_current_task_proto = { .ret_type = RET_INTEGER, }; +BPF_CALL_0(bpf_get_current_task_btf) +{ + return (unsigned long) current; +} + +BTF_ID_LIST_SINGLE(bpf_get_current_btf_ids, struct, task_struct) + +static const struct bpf_func_proto bpf_get_current_task_btf_proto = { + .func = bpf_get_current_task_btf, + .gpl_only = true, + .ret_type = RET_PTR_TO_BTF_ID, + .ret_btf_id = &bpf_get_current_btf_ids[0], +}; + BPF_CALL_2(bpf_current_task_under_cgroup, struct bpf_map *, map, u32, idx) { struct bpf_array *array = container_of(map, struct bpf_array, map); @@ -1265,6 +1279,8 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_get_current_pid_tgid_proto; case BPF_FUNC_get_current_task: return &bpf_get_current_task_proto; + case BPF_FUNC_get_current_task_btf: + return &bpf_get_current_task_btf_proto; case BPF_FUNC_get_current_uid_gid: return &bpf_get_current_uid_gid_proto; case BPF_FUNC_get_current_comm: diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index f4037b2161a6..9879d6793e90 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -3779,6 +3779,14 @@ union bpf_attr { * 0 on success. * * **-ENOENT** if the bpf_local_storage cannot be found. + * + * struct task_struct *bpf_get_current_task_btf(void) + * Description + * Return a BTF pointer to the "current" task. + * This pointer can also be used in helpers that accept an + * *ARG_PTR_TO_BTF_ID* of type *task_struct*. + * Return + * Pointer to the current task. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -3939,6 +3947,7 @@ union bpf_attr { FN(redirect_peer), \ FN(task_storage_get), \ FN(task_storage_delete), \ + FN(get_current_task_btf), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper