1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3 #include <linux/kernel.h>
4 #include <linux/filter.h>
7 #include "libbpf_common.h"
8 #include "libbpf_internal.h"
11 static inline __u64
ptr_to_u64(const void *ptr
)
13 return (__u64
)(unsigned long)ptr
;
23 static int probe_kern_prog_name(int token_fd
)
25 const size_t attr_sz
= offsetofend(union bpf_attr
, prog_token_fd
);
26 struct bpf_insn insns
[] = {
27 BPF_MOV64_IMM(BPF_REG_0
, 0),
33 memset(&attr
, 0, attr_sz
);
34 attr
.prog_type
= BPF_PROG_TYPE_SOCKET_FILTER
;
35 attr
.license
= ptr_to_u64("GPL");
36 attr
.insns
= ptr_to_u64(insns
);
37 attr
.insn_cnt
= (__u32
)ARRAY_SIZE(insns
);
38 attr
.prog_token_fd
= token_fd
;
40 attr
.prog_flags
|= BPF_F_TOKEN_FD
;
41 libbpf_strlcpy(attr
.prog_name
, "libbpf_nametest", sizeof(attr
.prog_name
));
43 /* make sure loading with name works */
44 ret
= sys_bpf_prog_load(&attr
, attr_sz
, PROG_LOAD_ATTEMPTS
);
48 static int probe_kern_global_data(int token_fd
)
50 struct bpf_insn insns
[] = {
51 BPF_LD_MAP_VALUE(BPF_REG_1
, 0, 16),
52 BPF_ST_MEM(BPF_DW
, BPF_REG_1
, 0, 42),
53 BPF_MOV64_IMM(BPF_REG_0
, 0),
56 LIBBPF_OPTS(bpf_map_create_opts
, map_opts
,
58 .map_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
60 LIBBPF_OPTS(bpf_prog_load_opts
, prog_opts
,
62 .prog_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
64 int ret
, map
, insn_cnt
= ARRAY_SIZE(insns
);
66 map
= bpf_map_create(BPF_MAP_TYPE_ARRAY
, "libbpf_global", sizeof(int), 32, 1, &map_opts
);
69 pr_warn("Error in %s(): %s. Couldn't create simple array map.\n",
70 __func__
, errstr(ret
));
76 ret
= bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER
, NULL
, "GPL", insns
, insn_cnt
, &prog_opts
);
81 static int probe_kern_btf(int token_fd
)
83 static const char strs
[] = "\0int";
86 BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED
, 0, 32, 4),
89 return probe_fd(libbpf__load_raw_btf((char *)types
, sizeof(types
),
90 strs
, sizeof(strs
), token_fd
));
93 static int probe_kern_btf_func(int token_fd
)
95 static const char strs
[] = "\0int\0x\0a";
96 /* void x(int a) {} */
99 BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED
, 0, 32, 4), /* [1] */
100 /* FUNC_PROTO */ /* [2] */
101 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO
, 0, 1), 0),
103 /* FUNC x */ /* [3] */
104 BTF_TYPE_ENC(5, BTF_INFO_ENC(BTF_KIND_FUNC
, 0, 0), 2),
107 return probe_fd(libbpf__load_raw_btf((char *)types
, sizeof(types
),
108 strs
, sizeof(strs
), token_fd
));
111 static int probe_kern_btf_func_global(int token_fd
)
113 static const char strs
[] = "\0int\0x\0a";
114 /* static void x(int a) {} */
117 BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED
, 0, 32, 4), /* [1] */
118 /* FUNC_PROTO */ /* [2] */
119 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO
, 0, 1), 0),
121 /* FUNC x BTF_FUNC_GLOBAL */ /* [3] */
122 BTF_TYPE_ENC(5, BTF_INFO_ENC(BTF_KIND_FUNC
, 0, BTF_FUNC_GLOBAL
), 2),
125 return probe_fd(libbpf__load_raw_btf((char *)types
, sizeof(types
),
126 strs
, sizeof(strs
), token_fd
));
129 static int probe_kern_btf_datasec(int token_fd
)
131 static const char strs
[] = "\0x\0.data";
135 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED
, 0, 32, 4), /* [1] */
136 /* VAR x */ /* [2] */
137 BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_VAR
, 0, 0), 1),
139 /* DATASEC val */ /* [3] */
140 BTF_TYPE_ENC(3, BTF_INFO_ENC(BTF_KIND_DATASEC
, 0, 1), 4),
141 BTF_VAR_SECINFO_ENC(2, 0, 4),
144 return probe_fd(libbpf__load_raw_btf((char *)types
, sizeof(types
),
145 strs
, sizeof(strs
), token_fd
));
148 static int probe_kern_btf_qmark_datasec(int token_fd
)
150 static const char strs
[] = "\0x\0?.data";
154 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED
, 0, 32, 4), /* [1] */
155 /* VAR x */ /* [2] */
156 BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_VAR
, 0, 0), 1),
158 /* DATASEC ?.data */ /* [3] */
159 BTF_TYPE_ENC(3, BTF_INFO_ENC(BTF_KIND_DATASEC
, 0, 1), 4),
160 BTF_VAR_SECINFO_ENC(2, 0, 4),
163 return probe_fd(libbpf__load_raw_btf((char *)types
, sizeof(types
),
164 strs
, sizeof(strs
), token_fd
));
167 static int probe_kern_btf_float(int token_fd
)
169 static const char strs
[] = "\0float";
172 BTF_TYPE_FLOAT_ENC(1, 4),
175 return probe_fd(libbpf__load_raw_btf((char *)types
, sizeof(types
),
176 strs
, sizeof(strs
), token_fd
));
179 static int probe_kern_btf_decl_tag(int token_fd
)
181 static const char strs
[] = "\0tag";
184 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED
, 0, 32, 4), /* [1] */
185 /* VAR x */ /* [2] */
186 BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_VAR
, 0, 0), 1),
189 BTF_TYPE_DECL_TAG_ENC(1, 2, -1),
192 return probe_fd(libbpf__load_raw_btf((char *)types
, sizeof(types
),
193 strs
, sizeof(strs
), token_fd
));
196 static int probe_kern_btf_type_tag(int token_fd
)
198 static const char strs
[] = "\0tag";
201 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED
, 0, 32, 4), /* [1] */
203 BTF_TYPE_TYPE_TAG_ENC(1, 1), /* [2] */
205 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR
, 0, 0), 2), /* [3] */
208 return probe_fd(libbpf__load_raw_btf((char *)types
, sizeof(types
),
209 strs
, sizeof(strs
), token_fd
));
212 static int probe_kern_array_mmap(int token_fd
)
214 LIBBPF_OPTS(bpf_map_create_opts
, opts
,
215 .map_flags
= BPF_F_MMAPABLE
| (token_fd
? BPF_F_TOKEN_FD
: 0),
216 .token_fd
= token_fd
,
220 fd
= bpf_map_create(BPF_MAP_TYPE_ARRAY
, "libbpf_mmap", sizeof(int), sizeof(int), 1, &opts
);
224 static int probe_kern_exp_attach_type(int token_fd
)
226 LIBBPF_OPTS(bpf_prog_load_opts
, opts
,
227 .expected_attach_type
= BPF_CGROUP_INET_SOCK_CREATE
,
228 .token_fd
= token_fd
,
229 .prog_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
231 struct bpf_insn insns
[] = {
232 BPF_MOV64_IMM(BPF_REG_0
, 0),
235 int fd
, insn_cnt
= ARRAY_SIZE(insns
);
237 /* use any valid combination of program type and (optional)
238 * non-zero expected attach type (i.e., not a BPF_CGROUP_INET_INGRESS)
239 * to see if kernel supports expected_attach_type field for
240 * BPF_PROG_LOAD command
242 fd
= bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK
, NULL
, "GPL", insns
, insn_cnt
, &opts
);
246 static int probe_kern_probe_read_kernel(int token_fd
)
248 LIBBPF_OPTS(bpf_prog_load_opts
, opts
,
249 .token_fd
= token_fd
,
250 .prog_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
252 struct bpf_insn insns
[] = {
253 BPF_MOV64_REG(BPF_REG_1
, BPF_REG_10
), /* r1 = r10 (fp) */
254 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_1
, -8), /* r1 += -8 */
255 BPF_MOV64_IMM(BPF_REG_2
, 8), /* r2 = 8 */
256 BPF_MOV64_IMM(BPF_REG_3
, 0), /* r3 = 0 */
257 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
, 0, 0, 0, BPF_FUNC_probe_read_kernel
),
260 int fd
, insn_cnt
= ARRAY_SIZE(insns
);
262 fd
= bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT
, NULL
, "GPL", insns
, insn_cnt
, &opts
);
266 static int probe_prog_bind_map(int token_fd
)
268 struct bpf_insn insns
[] = {
269 BPF_MOV64_IMM(BPF_REG_0
, 0),
272 LIBBPF_OPTS(bpf_map_create_opts
, map_opts
,
273 .token_fd
= token_fd
,
274 .map_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
276 LIBBPF_OPTS(bpf_prog_load_opts
, prog_opts
,
277 .token_fd
= token_fd
,
278 .prog_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
280 int ret
, map
, prog
, insn_cnt
= ARRAY_SIZE(insns
);
282 map
= bpf_map_create(BPF_MAP_TYPE_ARRAY
, "libbpf_det_bind", sizeof(int), 32, 1, &map_opts
);
285 pr_warn("Error in %s(): %s. Couldn't create simple array map.\n",
286 __func__
, errstr(ret
));
290 prog
= bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER
, NULL
, "GPL", insns
, insn_cnt
, &prog_opts
);
296 ret
= bpf_prog_bind_map(prog
, map
, NULL
);
304 static int probe_module_btf(int token_fd
)
306 static const char strs
[] = "\0int";
309 BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED
, 0, 32, 4),
311 struct bpf_btf_info info
;
312 __u32 len
= sizeof(info
);
316 fd
= libbpf__load_raw_btf((char *)types
, sizeof(types
), strs
, sizeof(strs
), token_fd
);
318 return 0; /* BTF not supported at all */
320 memset(&info
, 0, sizeof(info
));
321 info
.name
= ptr_to_u64(name
);
322 info
.name_len
= sizeof(name
);
324 /* check that BPF_OBJ_GET_INFO_BY_FD supports specifying name pointer;
325 * kernel's module BTF support coincides with support for
326 * name/name_len fields in struct bpf_btf_info.
328 err
= bpf_btf_get_info_by_fd(fd
, &info
, &len
);
333 static int probe_perf_link(int token_fd
)
335 struct bpf_insn insns
[] = {
336 BPF_MOV64_IMM(BPF_REG_0
, 0),
339 LIBBPF_OPTS(bpf_prog_load_opts
, opts
,
340 .token_fd
= token_fd
,
341 .prog_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
343 int prog_fd
, link_fd
, err
;
345 prog_fd
= bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT
, NULL
, "GPL",
346 insns
, ARRAY_SIZE(insns
), &opts
);
350 /* use invalid perf_event FD to get EBADF, if link is supported;
351 * otherwise EINVAL should be returned
353 link_fd
= bpf_link_create(prog_fd
, -1, BPF_PERF_EVENT
, NULL
);
354 err
= -errno
; /* close() can clobber errno */
360 return link_fd
< 0 && err
== -EBADF
;
363 static int probe_uprobe_multi_link(int token_fd
)
365 LIBBPF_OPTS(bpf_prog_load_opts
, load_opts
,
366 .expected_attach_type
= BPF_TRACE_UPROBE_MULTI
,
367 .token_fd
= token_fd
,
368 .prog_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
370 LIBBPF_OPTS(bpf_link_create_opts
, link_opts
);
371 struct bpf_insn insns
[] = {
372 BPF_MOV64_IMM(BPF_REG_0
, 0),
375 int prog_fd
, link_fd
, err
;
376 unsigned long offset
= 0;
378 prog_fd
= bpf_prog_load(BPF_PROG_TYPE_KPROBE
, NULL
, "GPL",
379 insns
, ARRAY_SIZE(insns
), &load_opts
);
383 /* Creating uprobe in '/' binary should fail with -EBADF. */
384 link_opts
.uprobe_multi
.path
= "/";
385 link_opts
.uprobe_multi
.offsets
= &offset
;
386 link_opts
.uprobe_multi
.cnt
= 1;
388 link_fd
= bpf_link_create(prog_fd
, -1, BPF_TRACE_UPROBE_MULTI
, &link_opts
);
389 err
= -errno
; /* close() can clobber errno */
391 if (link_fd
>= 0 || err
!= -EBADF
) {
398 /* Initial multi-uprobe support in kernel didn't handle PID filtering
399 * correctly (it was doing thread filtering, not process filtering).
400 * So now we'll detect if PID filtering logic was fixed, and, if not,
401 * we'll pretend multi-uprobes are not supported, if not.
402 * Multi-uprobes are used in USDT attachment logic, and we need to be
403 * conservative here, because multi-uprobe selection happens early at
404 * load time, while the use of PID filtering is known late at
405 * attachment time, at which point it's too late to undo multi-uprobe
408 * Creating uprobe with pid == -1 for (invalid) '/' binary will fail
409 * early with -EINVAL on kernels with fixed PID filtering logic;
410 * otherwise -ESRCH would be returned if passed correct binary path
411 * (but we'll just get -BADF, of course).
413 link_opts
.uprobe_multi
.pid
= -1; /* invalid PID */
414 link_opts
.uprobe_multi
.path
= "/"; /* invalid path */
415 link_opts
.uprobe_multi
.offsets
= &offset
;
416 link_opts
.uprobe_multi
.cnt
= 1;
418 link_fd
= bpf_link_create(prog_fd
, -1, BPF_TRACE_UPROBE_MULTI
, &link_opts
);
419 err
= -errno
; /* close() can clobber errno */
425 return link_fd
< 0 && err
== -EINVAL
;
428 static int probe_kern_bpf_cookie(int token_fd
)
430 struct bpf_insn insns
[] = {
431 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
, 0, 0, 0, BPF_FUNC_get_attach_cookie
),
434 LIBBPF_OPTS(bpf_prog_load_opts
, opts
,
435 .token_fd
= token_fd
,
436 .prog_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
438 int ret
, insn_cnt
= ARRAY_SIZE(insns
);
440 ret
= bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT
, NULL
, "GPL", insns
, insn_cnt
, &opts
);
441 return probe_fd(ret
);
444 static int probe_kern_btf_enum64(int token_fd
)
446 static const char strs
[] = "\0enum64";
448 BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_ENUM64
, 0, 0), 8),
451 return probe_fd(libbpf__load_raw_btf((char *)types
, sizeof(types
),
452 strs
, sizeof(strs
), token_fd
));
455 static int probe_kern_arg_ctx_tag(int token_fd
)
457 static const char strs
[] = "\0a\0b\0arg:ctx\0";
458 const __u32 types
[] = {
460 BTF_TYPE_INT_ENC(1 /* "a" */, BTF_INT_SIGNED
, 0, 32, 4),
461 /* [2] PTR -> VOID */
462 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR
, 0, 0), 0),
463 /* [3] FUNC_PROTO `int(void *a)` */
464 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO
, 0, 1), 1),
465 BTF_PARAM_ENC(1 /* "a" */, 2),
466 /* [4] FUNC 'a' -> FUNC_PROTO (main prog) */
467 BTF_TYPE_ENC(1 /* "a" */, BTF_INFO_ENC(BTF_KIND_FUNC
, 0, BTF_FUNC_GLOBAL
), 3),
468 /* [5] FUNC_PROTO `int(void *b __arg_ctx)` */
469 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO
, 0, 1), 1),
470 BTF_PARAM_ENC(3 /* "b" */, 2),
471 /* [6] FUNC 'b' -> FUNC_PROTO (subprog) */
472 BTF_TYPE_ENC(3 /* "b" */, BTF_INFO_ENC(BTF_KIND_FUNC
, 0, BTF_FUNC_GLOBAL
), 5),
473 /* [7] DECL_TAG 'arg:ctx' -> func 'b' arg 'b' */
474 BTF_TYPE_DECL_TAG_ENC(5 /* "arg:ctx" */, 6, 0),
476 const struct bpf_insn insns
[] = {
481 BPF_EMIT_CALL(BPF_FUNC_get_func_ip
), /* needs PTR_TO_CTX */
484 const struct bpf_func_info_min func_infos
[] = {
485 { 0, 4 }, /* main prog -> FUNC 'a' */
486 { 2, 6 }, /* subprog -> FUNC 'b' */
488 LIBBPF_OPTS(bpf_prog_load_opts
, opts
,
489 .token_fd
= token_fd
,
490 .prog_flags
= token_fd
? BPF_F_TOKEN_FD
: 0,
492 int prog_fd
, btf_fd
, insn_cnt
= ARRAY_SIZE(insns
);
494 btf_fd
= libbpf__load_raw_btf((char *)types
, sizeof(types
), strs
, sizeof(strs
), token_fd
);
498 opts
.prog_btf_fd
= btf_fd
;
499 opts
.func_info
= &func_infos
;
500 opts
.func_info_cnt
= ARRAY_SIZE(func_infos
);
501 opts
.func_info_rec_size
= sizeof(func_infos
[0]);
503 prog_fd
= bpf_prog_load(BPF_PROG_TYPE_KPROBE
, "det_arg_ctx",
504 "GPL", insns
, insn_cnt
, &opts
);
507 return probe_fd(prog_fd
);
510 typedef int (*feature_probe_fn
)(int /* token_fd */);
512 static struct kern_feature_cache feature_cache
;
514 static struct kern_feature_desc
{
516 feature_probe_fn probe
;
517 } feature_probes
[__FEAT_CNT
] = {
519 "BPF program name", probe_kern_prog_name
,
521 [FEAT_GLOBAL_DATA
] = {
522 "global variables", probe_kern_global_data
,
525 "minimal BTF", probe_kern_btf
,
528 "BTF functions", probe_kern_btf_func
,
530 [FEAT_BTF_GLOBAL_FUNC
] = {
531 "BTF global function", probe_kern_btf_func_global
,
533 [FEAT_BTF_DATASEC
] = {
534 "BTF data section and variable", probe_kern_btf_datasec
,
536 [FEAT_ARRAY_MMAP
] = {
537 "ARRAY map mmap()", probe_kern_array_mmap
,
539 [FEAT_EXP_ATTACH_TYPE
] = {
540 "BPF_PROG_LOAD expected_attach_type attribute",
541 probe_kern_exp_attach_type
,
543 [FEAT_PROBE_READ_KERN
] = {
544 "bpf_probe_read_kernel() helper", probe_kern_probe_read_kernel
,
546 [FEAT_PROG_BIND_MAP
] = {
547 "BPF_PROG_BIND_MAP support", probe_prog_bind_map
,
549 [FEAT_MODULE_BTF
] = {
550 "module BTF support", probe_module_btf
,
553 "BTF_KIND_FLOAT support", probe_kern_btf_float
,
556 "BPF perf link support", probe_perf_link
,
558 [FEAT_BTF_DECL_TAG
] = {
559 "BTF_KIND_DECL_TAG support", probe_kern_btf_decl_tag
,
561 [FEAT_BTF_TYPE_TAG
] = {
562 "BTF_KIND_TYPE_TAG support", probe_kern_btf_type_tag
,
564 [FEAT_MEMCG_ACCOUNT
] = {
565 "memcg-based memory accounting", probe_memcg_account
,
567 [FEAT_BPF_COOKIE
] = {
568 "BPF cookie support", probe_kern_bpf_cookie
,
570 [FEAT_BTF_ENUM64
] = {
571 "BTF_KIND_ENUM64 support", probe_kern_btf_enum64
,
573 [FEAT_SYSCALL_WRAPPER
] = {
574 "Kernel using syscall wrapper", probe_kern_syscall_wrapper
,
576 [FEAT_UPROBE_MULTI_LINK
] = {
577 "BPF multi-uprobe link support", probe_uprobe_multi_link
,
579 [FEAT_ARG_CTX_TAG
] = {
580 "kernel-side __arg_ctx tag", probe_kern_arg_ctx_tag
,
582 [FEAT_BTF_QMARK_DATASEC
] = {
583 "BTF DATASEC names starting from '?'", probe_kern_btf_qmark_datasec
,
587 bool feat_supported(struct kern_feature_cache
*cache
, enum kern_feature_id feat_id
)
589 struct kern_feature_desc
*feat
= &feature_probes
[feat_id
];
592 /* assume global feature cache, unless custom one is provided */
594 cache
= &feature_cache
;
596 if (READ_ONCE(cache
->res
[feat_id
]) == FEAT_UNKNOWN
) {
597 ret
= feat
->probe(cache
->token_fd
);
599 WRITE_ONCE(cache
->res
[feat_id
], FEAT_SUPPORTED
);
600 } else if (ret
== 0) {
601 WRITE_ONCE(cache
->res
[feat_id
], FEAT_MISSING
);
603 pr_warn("Detection of kernel %s support failed: %s\n",
604 feat
->desc
, errstr(ret
));
605 WRITE_ONCE(cache
->res
[feat_id
], FEAT_MISSING
);
609 return READ_ONCE(cache
->res
[feat_id
]) == FEAT_SUPPORTED
;