mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-26 00:21:17 +00:00
bpf: Add bpf_line_info support
This patch adds bpf_line_info support. It accepts an array of bpf_line_info objects during BPF_PROG_LOAD. The "line_info", "line_info_cnt" and "line_info_rec_size" are added to the "union bpf_attr". The "line_info_rec_size" makes bpf_line_info extensible in the future. The new "check_btf_line()" ensures the userspace line_info is valid for the kernel to use. When the verifier is translating/patching the bpf_prog (through "bpf_patch_insn_single()"), the line_infos' insn_off is also adjusted by the newly added "bpf_adj_linfo()". If the bpf_prog is jited, this patch also provides the jited addrs (in aux->jited_linfo) for the corresponding line_info.insn_off. "bpf_prog_fill_jited_linfo()" is added to fill the aux->jited_linfo. It is currently called by the x86 jit. Other jits can also use "bpf_prog_fill_jited_linfo()" and it will be done in the followup patches. In the future, if it deemed necessary, a particular jit could also provide its own "bpf_prog_fill_jited_linfo()" implementation. A few "*line_info*" fields are added to the bpf_prog_info such that the user can get the xlated line_info back (i.e. the line_info with its insn_off reflecting the translated prog). The jited_line_info is available if the prog is jited. It is an array of __u64. If the prog is not jited, jited_line_info_cnt is 0. The verifier's verbose log with line_info will be done in a follow up patch. Signed-off-by: Martin KaFai Lau <kafai@fb.com> Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
6baefa1aa4
commit
c454a46b5e
10 changed files with 419 additions and 33 deletions
|
@ -1215,6 +1215,7 @@ static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
|
|||
bpf_prog_kallsyms_del_all(prog);
|
||||
btf_put(prog->aux->btf);
|
||||
kvfree(prog->aux->func_info);
|
||||
bpf_prog_free_linfo(prog);
|
||||
|
||||
call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
|
||||
}
|
||||
|
@ -1439,7 +1440,7 @@ bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type,
|
|||
}
|
||||
|
||||
/* last field in 'union bpf_attr' used by this command */
|
||||
#define BPF_PROG_LOAD_LAST_FIELD func_info_cnt
|
||||
#define BPF_PROG_LOAD_LAST_FIELD line_info_cnt
|
||||
|
||||
static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
|
||||
{
|
||||
|
@ -1560,6 +1561,7 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
|
|||
return err;
|
||||
|
||||
free_used_maps:
|
||||
bpf_prog_free_linfo(prog);
|
||||
kvfree(prog->aux->func_info);
|
||||
btf_put(prog->aux->btf);
|
||||
bpf_prog_kallsyms_del_subprogs(prog);
|
||||
|
@ -2041,6 +2043,37 @@ static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog)
|
|||
return insns;
|
||||
}
|
||||
|
||||
static int set_info_rec_size(struct bpf_prog_info *info)
|
||||
{
|
||||
/*
|
||||
* Ensure info.*_rec_size is the same as kernel expected size
|
||||
*
|
||||
* or
|
||||
*
|
||||
* Only allow zero *_rec_size if both _rec_size and _cnt are
|
||||
* zero. In this case, the kernel will set the expected
|
||||
* _rec_size back to the info.
|
||||
*/
|
||||
|
||||
if ((info->func_info_cnt || info->func_info_rec_size) &&
|
||||
info->func_info_rec_size != sizeof(struct bpf_func_info))
|
||||
return -EINVAL;
|
||||
|
||||
if ((info->line_info_cnt || info->line_info_rec_size) &&
|
||||
info->line_info_rec_size != sizeof(struct bpf_line_info))
|
||||
return -EINVAL;
|
||||
|
||||
if ((info->jited_line_info_cnt || info->jited_line_info_rec_size) &&
|
||||
info->jited_line_info_rec_size != sizeof(__u64))
|
||||
return -EINVAL;
|
||||
|
||||
info->func_info_rec_size = sizeof(struct bpf_func_info);
|
||||
info->line_info_rec_size = sizeof(struct bpf_line_info);
|
||||
info->jited_line_info_rec_size = sizeof(__u64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
||||
const union bpf_attr *attr,
|
||||
union bpf_attr __user *uattr)
|
||||
|
@ -2083,11 +2116,9 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
if ((info.func_info_cnt || info.func_info_rec_size) &&
|
||||
info.func_info_rec_size != sizeof(struct bpf_func_info))
|
||||
return -EINVAL;
|
||||
|
||||
info.func_info_rec_size = sizeof(struct bpf_func_info);
|
||||
err = set_info_rec_size(&info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
info.jited_prog_len = 0;
|
||||
|
@ -2095,6 +2126,8 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
|||
info.nr_jited_ksyms = 0;
|
||||
info.nr_jited_func_lens = 0;
|
||||
info.func_info_cnt = 0;
|
||||
info.line_info_cnt = 0;
|
||||
info.jited_line_info_cnt = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -2251,6 +2284,44 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
|||
}
|
||||
}
|
||||
|
||||
ulen = info.line_info_cnt;
|
||||
info.line_info_cnt = prog->aux->nr_linfo;
|
||||
if (info.line_info_cnt && ulen) {
|
||||
if (bpf_dump_raw_ok()) {
|
||||
__u8 __user *user_linfo;
|
||||
|
||||
user_linfo = u64_to_user_ptr(info.line_info);
|
||||
ulen = min_t(u32, info.line_info_cnt, ulen);
|
||||
if (copy_to_user(user_linfo, prog->aux->linfo,
|
||||
info.line_info_rec_size * ulen))
|
||||
return -EFAULT;
|
||||
} else {
|
||||
info.line_info = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ulen = info.jited_line_info_cnt;
|
||||
if (prog->aux->jited_linfo)
|
||||
info.jited_line_info_cnt = prog->aux->nr_linfo;
|
||||
else
|
||||
info.jited_line_info_cnt = 0;
|
||||
if (info.jited_line_info_cnt && ulen) {
|
||||
if (bpf_dump_raw_ok()) {
|
||||
__u64 __user *user_linfo;
|
||||
u32 i;
|
||||
|
||||
user_linfo = u64_to_user_ptr(info.jited_line_info);
|
||||
ulen = min_t(u32, info.jited_line_info_cnt, ulen);
|
||||
for (i = 0; i < ulen; i++) {
|
||||
if (put_user((__u64)(long)prog->aux->jited_linfo[i],
|
||||
&user_linfo[i]))
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
info.jited_line_info = 0;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (copy_to_user(uinfo, &info, info_len) ||
|
||||
put_user(info_len, &uattr->info.info_len))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue