Skip to content

Commit dbecd73

Browse files
sandip4nborkmann
authored andcommitted
bpf: get kernel symbol addresses via syscall
This adds new two new fields to struct bpf_prog_info. For multi-function programs, these fields can be used to pass a list of kernel symbol addresses for all functions in a given program to userspace using the bpf system call with the BPF_OBJ_GET_INFO_BY_FD command. When bpf_jit_kallsyms is enabled, we can get the address of the corresponding kernel symbol for a callee function and resolve the symbol's name. The address is determined by adding the value of the call instruction's imm field to __bpf_call_base. This offset gets assigned to the imm field by the verifier. For some architectures, such as powerpc64, the imm field is not large enough to hold this offset. We resolve this by: [1] Assigning the subprog id to the imm field of a call instruction in the verifier instead of the offset of the callee's symbol's address from __bpf_call_base. [2] Determining the address of a callee's corresponding symbol by using the imm field as an index for the list of kernel symbol addresses now available from the program info. Suggested-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Sandipan Das <sandipan@linux.vnet.ibm.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
1 parent 8484ce8 commit dbecd73

File tree

3 files changed

+28
-6
lines changed

3 files changed

+28
-6
lines changed

include/uapi/linux/bpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2205,6 +2205,8 @@ struct bpf_prog_info {
22052205
__u32 gpl_compatible:1;
22062206
__u64 netns_dev;
22072207
__u64 netns_ino;
2208+
__u32 nr_jited_ksyms;
2209+
__aligned_u64 jited_ksyms;
22082210
} __attribute__((aligned(8)));
22092211

22102212
struct bpf_map_info {

kernel/bpf/syscall.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,6 +1933,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
19331933
if (!capable(CAP_SYS_ADMIN)) {
19341934
info.jited_prog_len = 0;
19351935
info.xlated_prog_len = 0;
1936+
info.nr_jited_ksyms = 0;
19361937
goto done;
19371938
}
19381939

@@ -1981,6 +1982,30 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
19811982
}
19821983
}
19831984

1985+
ulen = info.nr_jited_ksyms;
1986+
info.nr_jited_ksyms = prog->aux->func_cnt;
1987+
if (info.nr_jited_ksyms && ulen) {
1988+
if (bpf_dump_raw_ok()) {
1989+
u64 __user *user_ksyms;
1990+
ulong ksym_addr;
1991+
u32 i;
1992+
1993+
/* copy the address of the kernel symbol
1994+
* corresponding to each function
1995+
*/
1996+
ulen = min_t(u32, info.nr_jited_ksyms, ulen);
1997+
user_ksyms = u64_to_user_ptr(info.jited_ksyms);
1998+
for (i = 0; i < ulen; i++) {
1999+
ksym_addr = (ulong) prog->aux->func[i]->bpf_func;
2000+
ksym_addr &= PAGE_MASK;
2001+
if (put_user((u64) ksym_addr, &user_ksyms[i]))
2002+
return -EFAULT;
2003+
}
2004+
} else {
2005+
info.jited_ksyms = 0;
2006+
}
2007+
}
2008+
19842009
done:
19852010
if (copy_to_user(uinfo, &info, info_len) ||
19862011
put_user(info_len, &uattr->info.info_len))

kernel/bpf/verifier.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5426,17 +5426,12 @@ static int jit_subprogs(struct bpf_verifier_env *env)
54265426
* later look the same as if they were interpreted only.
54275427
*/
54285428
for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
5429-
unsigned long addr;
5430-
54315429
if (insn->code != (BPF_JMP | BPF_CALL) ||
54325430
insn->src_reg != BPF_PSEUDO_CALL)
54335431
continue;
54345432
insn->off = env->insn_aux_data[i].call_imm;
54355433
subprog = find_subprog(env, i + insn->off + 1);
5436-
addr = (unsigned long)func[subprog]->bpf_func;
5437-
addr &= PAGE_MASK;
5438-
insn->imm = (u64 (*)(u64, u64, u64, u64, u64))
5439-
addr - __bpf_call_base;
5434+
insn->imm = subprog;
54405435
}
54415436

54425437
prog->jited = 1;

0 commit comments

Comments
 (0)