mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
libbpf: integrate __arg_ctx feature detector into kernel_supports()
Now that feature detection code is in bpf-next tree, integrate __arg_ctx kernel-side support into kernel_supports() framework. Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/r/20240125205510.3642094-2-andrii@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
ced33f2cfa
commit
0e6d0a9d23
@ -407,6 +407,61 @@ static int probe_kern_btf_enum64(int token_fd)
|
||||
strs, sizeof(strs), token_fd));
|
||||
}
|
||||
|
||||
static int probe_kern_arg_ctx_tag(int token_fd)
|
||||
{
|
||||
static const char strs[] = "\0a\0b\0arg:ctx\0";
|
||||
const __u32 types[] = {
|
||||
/* [1] INT */
|
||||
BTF_TYPE_INT_ENC(1 /* "a" */, BTF_INT_SIGNED, 0, 32, 4),
|
||||
/* [2] PTR -> VOID */
|
||||
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
|
||||
/* [3] FUNC_PROTO `int(void *a)` */
|
||||
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 1),
|
||||
BTF_PARAM_ENC(1 /* "a" */, 2),
|
||||
/* [4] FUNC 'a' -> FUNC_PROTO (main prog) */
|
||||
BTF_TYPE_ENC(1 /* "a" */, BTF_INFO_ENC(BTF_KIND_FUNC, 0, BTF_FUNC_GLOBAL), 3),
|
||||
/* [5] FUNC_PROTO `int(void *b __arg_ctx)` */
|
||||
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 1),
|
||||
BTF_PARAM_ENC(3 /* "b" */, 2),
|
||||
/* [6] FUNC 'b' -> FUNC_PROTO (subprog) */
|
||||
BTF_TYPE_ENC(3 /* "b" */, BTF_INFO_ENC(BTF_KIND_FUNC, 0, BTF_FUNC_GLOBAL), 5),
|
||||
/* [7] DECL_TAG 'arg:ctx' -> func 'b' arg 'b' */
|
||||
BTF_TYPE_DECL_TAG_ENC(5 /* "arg:ctx" */, 6, 0),
|
||||
};
|
||||
const struct bpf_insn insns[] = {
|
||||
/* main prog */
|
||||
BPF_CALL_REL(+1),
|
||||
BPF_EXIT_INSN(),
|
||||
/* global subprog */
|
||||
BPF_EMIT_CALL(BPF_FUNC_get_func_ip), /* needs PTR_TO_CTX */
|
||||
BPF_EXIT_INSN(),
|
||||
};
|
||||
const struct bpf_func_info_min func_infos[] = {
|
||||
{ 0, 4 }, /* main prog -> FUNC 'a' */
|
||||
{ 2, 6 }, /* subprog -> FUNC 'b' */
|
||||
};
|
||||
LIBBPF_OPTS(bpf_prog_load_opts, opts,
|
||||
.token_fd = token_fd,
|
||||
.prog_flags = token_fd ? BPF_F_TOKEN_FD : 0,
|
||||
);
|
||||
int prog_fd, btf_fd, insn_cnt = ARRAY_SIZE(insns);
|
||||
|
||||
btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types), strs, sizeof(strs), token_fd);
|
||||
if (btf_fd < 0)
|
||||
return 0;
|
||||
|
||||
opts.prog_btf_fd = btf_fd;
|
||||
opts.func_info = &func_infos;
|
||||
opts.func_info_cnt = ARRAY_SIZE(func_infos);
|
||||
opts.func_info_rec_size = sizeof(func_infos[0]);
|
||||
|
||||
prog_fd = bpf_prog_load(BPF_PROG_TYPE_KPROBE, "det_arg_ctx",
|
||||
"GPL", insns, insn_cnt, &opts);
|
||||
close(btf_fd);
|
||||
|
||||
return probe_fd(prog_fd);
|
||||
}
|
||||
|
||||
typedef int (*feature_probe_fn)(int /* token_fd */);
|
||||
|
||||
static struct kern_feature_cache feature_cache;
|
||||
@ -476,6 +531,9 @@ static struct kern_feature_desc {
|
||||
[FEAT_UPROBE_MULTI_LINK] = {
|
||||
"BPF multi-uprobe link support", probe_uprobe_multi_link,
|
||||
},
|
||||
[FEAT_ARG_CTX_TAG] = {
|
||||
"kernel-side __arg_ctx tag", probe_kern_arg_ctx_tag,
|
||||
},
|
||||
};
|
||||
|
||||
bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_id)
|
||||
|
@ -6462,69 +6462,6 @@ static int clone_func_btf_info(struct btf *btf, int orig_fn_id, struct bpf_progr
|
||||
return fn_id;
|
||||
}
|
||||
|
||||
static int probe_kern_arg_ctx_tag(void)
|
||||
{
|
||||
/* To minimize merge conflicts with BPF token series that refactors
|
||||
* feature detection code a lot, we don't integrate
|
||||
* probe_kern_arg_ctx_tag() into kernel_supports() feature-detection
|
||||
* framework yet, doing our own caching internally.
|
||||
* This will be cleaned up a bit later when bpf/bpf-next trees settle.
|
||||
*/
|
||||
static int cached_result = -1;
|
||||
static const char strs[] = "\0a\0b\0arg:ctx\0";
|
||||
const __u32 types[] = {
|
||||
/* [1] INT */
|
||||
BTF_TYPE_INT_ENC(1 /* "a" */, BTF_INT_SIGNED, 0, 32, 4),
|
||||
/* [2] PTR -> VOID */
|
||||
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
|
||||
/* [3] FUNC_PROTO `int(void *a)` */
|
||||
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 1),
|
||||
BTF_PARAM_ENC(1 /* "a" */, 2),
|
||||
/* [4] FUNC 'a' -> FUNC_PROTO (main prog) */
|
||||
BTF_TYPE_ENC(1 /* "a" */, BTF_INFO_ENC(BTF_KIND_FUNC, 0, BTF_FUNC_GLOBAL), 3),
|
||||
/* [5] FUNC_PROTO `int(void *b __arg_ctx)` */
|
||||
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 1),
|
||||
BTF_PARAM_ENC(3 /* "b" */, 2),
|
||||
/* [6] FUNC 'b' -> FUNC_PROTO (subprog) */
|
||||
BTF_TYPE_ENC(3 /* "b" */, BTF_INFO_ENC(BTF_KIND_FUNC, 0, BTF_FUNC_GLOBAL), 5),
|
||||
/* [7] DECL_TAG 'arg:ctx' -> func 'b' arg 'b' */
|
||||
BTF_TYPE_DECL_TAG_ENC(5 /* "arg:ctx" */, 6, 0),
|
||||
};
|
||||
const struct bpf_insn insns[] = {
|
||||
/* main prog */
|
||||
BPF_CALL_REL(+1),
|
||||
BPF_EXIT_INSN(),
|
||||
/* global subprog */
|
||||
BPF_EMIT_CALL(BPF_FUNC_get_func_ip), /* needs PTR_TO_CTX */
|
||||
BPF_EXIT_INSN(),
|
||||
};
|
||||
const struct bpf_func_info_min func_infos[] = {
|
||||
{ 0, 4 }, /* main prog -> FUNC 'a' */
|
||||
{ 2, 6 }, /* subprog -> FUNC 'b' */
|
||||
};
|
||||
LIBBPF_OPTS(bpf_prog_load_opts, opts);
|
||||
int prog_fd, btf_fd, insn_cnt = ARRAY_SIZE(insns);
|
||||
|
||||
if (cached_result >= 0)
|
||||
return cached_result;
|
||||
|
||||
btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types), strs, sizeof(strs), 0);
|
||||
if (btf_fd < 0)
|
||||
return 0;
|
||||
|
||||
opts.prog_btf_fd = btf_fd;
|
||||
opts.func_info = &func_infos;
|
||||
opts.func_info_cnt = ARRAY_SIZE(func_infos);
|
||||
opts.func_info_rec_size = sizeof(func_infos[0]);
|
||||
|
||||
prog_fd = bpf_prog_load(BPF_PROG_TYPE_KPROBE, "det_arg_ctx",
|
||||
"GPL", insns, insn_cnt, &opts);
|
||||
close(btf_fd);
|
||||
|
||||
cached_result = probe_fd(prog_fd);
|
||||
return cached_result;
|
||||
}
|
||||
|
||||
/* Check if main program or global subprog's function prototype has `arg:ctx`
|
||||
* argument tags, and, if necessary, substitute correct type to match what BPF
|
||||
* verifier would expect, taking into account specific program type. This
|
||||
@ -6549,7 +6486,7 @@ static int bpf_program_fixup_func_info(struct bpf_object *obj, struct bpf_progra
|
||||
return 0;
|
||||
|
||||
/* don't do any fix ups if kernel natively supports __arg_ctx */
|
||||
if (probe_kern_arg_ctx_tag() > 0)
|
||||
if (kernel_supports(obj, FEAT_ARG_CTX_TAG))
|
||||
return 0;
|
||||
|
||||
/* some BPF program types just don't have named context structs, so
|
||||
|
@ -372,6 +372,8 @@ enum kern_feature_id {
|
||||
FEAT_SYSCALL_WRAPPER,
|
||||
/* BPF multi-uprobe link support */
|
||||
FEAT_UPROBE_MULTI_LINK,
|
||||
/* Kernel supports arg:ctx tag (__arg_ctx) for global subprogs natively */
|
||||
FEAT_ARG_CTX_TAG,
|
||||
__FEAT_CNT,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user