On Tue, Oct 5, 2021 at 5:29 PM Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> wrote: > > This helper allows us to get the address of a kernel symbol from inside > a BPF_PROG_TYPE_SYSCALL prog (used by gen_loader), so that we can > relocate weak and typeless ksym vars. > > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> LGTM. Acked-by: Song Liu <songliubraving@xxxxxx> > --- > include/linux/bpf.h | 1 + > include/uapi/linux/bpf.h | 14 ++++++++++++++ > kernel/bpf/syscall.c | 24 ++++++++++++++++++++++++ > tools/include/uapi/linux/bpf.h | 14 ++++++++++++++ > 4 files changed, 53 insertions(+) > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index d604c8251d88..17206aae329d 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -2107,6 +2107,7 @@ extern const struct bpf_func_proto bpf_for_each_map_elem_proto; > extern const struct bpf_func_proto bpf_btf_find_by_name_kind_proto; > extern const struct bpf_func_proto bpf_sk_setsockopt_proto; > extern const struct bpf_func_proto bpf_sk_getsockopt_proto; > +extern const struct bpf_func_proto bpf_kallsyms_lookup_name_proto; > > const struct bpf_func_proto *tracing_prog_func_proto( > enum bpf_func_id func_id, const struct bpf_prog *prog); > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h > index 6fc59d61937a..bbd0a3f4e5f6 100644 > --- a/include/uapi/linux/bpf.h > +++ b/include/uapi/linux/bpf.h > @@ -4909,6 +4909,19 @@ union bpf_attr { > * Return > * The number of bytes written to the buffer, or a negative error > * in case of failure. > + * > + * long bpf_kallsyms_lookup_name(const char *name, int name_sz, int flags, u64 *res) > + * Description > + * Get the address of a kernel symbol, returned in *res*. *res* is > + * set to 0 if the symbol is not found. > + * Return > + * On success, zero. On error, a negative value. > + * > + * **-EINVAL** if *flags* is not zero. > + * > + * **-EINVAL** if string *name* is not the same size as *name_sz*. > + * > + * **-ENOENT** if symbol is not found. > */ > #define __BPF_FUNC_MAPPER(FN) \ > FN(unspec), \ > @@ -5089,6 +5102,7 @@ union bpf_attr { > FN(task_pt_regs), \ > FN(get_branch_snapshot), \ > FN(trace_vprintk), \ > + FN(kallsyms_lookup_name), \ > /* */ > > /* integer value in 'imm' field of BPF_CALL instruction selects which helper > diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c > index 4e50c0bfdb7d..073ca9ebe58b 100644 > --- a/kernel/bpf/syscall.c > +++ b/kernel/bpf/syscall.c > @@ -4753,6 +4753,28 @@ static const struct bpf_func_proto bpf_sys_close_proto = { > .arg1_type = ARG_ANYTHING, > }; > > +BPF_CALL_4(bpf_kallsyms_lookup_name, const char *, name, int, name_sz, int, flags, u64 *, res) > +{ > + if (flags) > + return -EINVAL; > + > + if (name_sz <= 1 || name[name_sz - 1]) > + return -EINVAL; > + > + *res = kallsyms_lookup_name(name); > + return *res ? 0 : -ENOENT; > +} > + > +const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = { > + .func = bpf_kallsyms_lookup_name, > + .gpl_only = true, > + .ret_type = RET_INTEGER, > + .arg1_type = ARG_PTR_TO_MEM, > + .arg2_type = ARG_CONST_SIZE, > + .arg3_type = ARG_ANYTHING, > + .arg4_type = ARG_PTR_TO_LONG, > +}; > + > static const struct bpf_func_proto * > syscall_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) > { > @@ -4763,6 +4785,8 @@ syscall_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) > return &bpf_btf_find_by_name_kind_proto; > case BPF_FUNC_sys_close: > return &bpf_sys_close_proto; > + case BPF_FUNC_kallsyms_lookup_name: > + return &bpf_kallsyms_lookup_name_proto; > default: > return tracing_prog_func_proto(func_id, prog); > } > diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h > index 6fc59d61937a..bbd0a3f4e5f6 100644 > --- a/tools/include/uapi/linux/bpf.h > +++ b/tools/include/uapi/linux/bpf.h > @@ -4909,6 +4909,19 @@ union bpf_attr { > * Return > * The number of bytes written to the buffer, or a negative error > * in case of failure. > + * > + * long bpf_kallsyms_lookup_name(const char *name, int name_sz, int flags, u64 *res) > + * Description > + * Get the address of a kernel symbol, returned in *res*. *res* is > + * set to 0 if the symbol is not found. > + * Return > + * On success, zero. On error, a negative value. > + * > + * **-EINVAL** if *flags* is not zero. > + * > + * **-EINVAL** if string *name* is not the same size as *name_sz*. > + * > + * **-ENOENT** if symbol is not found. > */ > #define __BPF_FUNC_MAPPER(FN) \ > FN(unspec), \ > @@ -5089,6 +5102,7 @@ union bpf_attr { > FN(task_pt_regs), \ > FN(get_branch_snapshot), \ > FN(trace_vprintk), \ > + FN(kallsyms_lookup_name), \ > /* */ > > /* integer value in 'imm' field of BPF_CALL instruction selects which helper > -- > 2.33.0 >