Skip to content

Commit d565183

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf-add-multi-uprobe-link'
Jiri Olsa says: ==================== bpf: Add multi uprobe link hi, this patchset is adding support to attach multiple uprobes and usdt probes through new uprobe_multi link. The current uprobe is attached through the perf event and attaching many uprobes takes a lot of time because of that. The main reason is that we need to install perf event for each probed function and profile shows perf event installation (perf_install_in_context) as culprit. The new uprobe_multi link just creates raw uprobes and attaches the bpf program to them without perf event being involved. In addition to being faster we also save file descriptors. For the current uprobe attach we use extra perf event fd for each probed function. The new link just need one fd that covers all the functions we are attaching to. v7 changes: - fixed task release on error path and re-org the error path to be more straightforward [Yonghong] - re-organized uprobe_prog_run locking to follow general pattern and removed might_fault check as it's not needed in uprobe/task context [Yonghong] There's support for bpftrace [2] and tetragon [1]. Also available at: https://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git uprobe_multi thanks, jirka [1] cilium/tetragon#936 [2] bpftrace/bpftrace@master...olsajiri:bpftrace:uprobe_multi [3] https://lore.kernel.org/bpf/[email protected]/ --- ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents acfadf2 + 8909a93 commit d565183

File tree

24 files changed

+1992
-323
lines changed

24 files changed

+1992
-323
lines changed

include/linux/trace_events.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
752752
u32 *fd_type, const char **buf,
753753
u64 *probe_offset, u64 *probe_addr);
754754
int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
755+
int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
755756
#else
756757
static inline unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)
757758
{
@@ -798,6 +799,11 @@ bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
798799
{
799800
return -EOPNOTSUPP;
800801
}
802+
static inline int
803+
bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
804+
{
805+
return -EOPNOTSUPP;
806+
}
801807
#endif
802808

803809
enum {

include/uapi/linux/bpf.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,7 @@ enum bpf_attach_type {
10391039
BPF_NETFILTER,
10401040
BPF_TCX_INGRESS,
10411041
BPF_TCX_EGRESS,
1042+
BPF_TRACE_UPROBE_MULTI,
10421043
__MAX_BPF_ATTACH_TYPE
10431044
};
10441045

@@ -1057,6 +1058,7 @@ enum bpf_link_type {
10571058
BPF_LINK_TYPE_STRUCT_OPS = 9,
10581059
BPF_LINK_TYPE_NETFILTER = 10,
10591060
BPF_LINK_TYPE_TCX = 11,
1061+
BPF_LINK_TYPE_UPROBE_MULTI = 12,
10601062
MAX_BPF_LINK_TYPE,
10611063
};
10621064

@@ -1186,7 +1188,16 @@ enum bpf_perf_event_type {
11861188
/* link_create.kprobe_multi.flags used in LINK_CREATE command for
11871189
* BPF_TRACE_KPROBE_MULTI attach type to create return probe.
11881190
*/
1189-
#define BPF_F_KPROBE_MULTI_RETURN (1U << 0)
1191+
enum {
1192+
BPF_F_KPROBE_MULTI_RETURN = (1U << 0)
1193+
};
1194+
1195+
/* link_create.uprobe_multi.flags used in LINK_CREATE command for
1196+
* BPF_TRACE_UPROBE_MULTI attach type to create return probe.
1197+
*/
1198+
enum {
1199+
BPF_F_UPROBE_MULTI_RETURN = (1U << 0)
1200+
};
11901201

11911202
/* link_create.netfilter.flags used in LINK_CREATE command for
11921203
* BPF_PROG_TYPE_NETFILTER to enable IP packet defragmentation.
@@ -1624,6 +1635,15 @@ union bpf_attr {
16241635
};
16251636
__u64 expected_revision;
16261637
} tcx;
1638+
struct {
1639+
__aligned_u64 path;
1640+
__aligned_u64 offsets;
1641+
__aligned_u64 ref_ctr_offsets;
1642+
__aligned_u64 cookies;
1643+
__u32 cnt;
1644+
__u32 flags;
1645+
__u32 pid;
1646+
} uprobe_multi;
16271647
};
16281648
} link_create;
16291649

kernel/bpf/syscall.c

Lines changed: 63 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2815,10 +2815,12 @@ static void bpf_link_free_id(int id)
28152815

28162816
/* Clean up bpf_link and corresponding anon_inode file and FD. After
28172817
* anon_inode is created, bpf_link can't be just kfree()'d due to deferred
2818-
* anon_inode's release() call. This helper marksbpf_link as
2818+
* anon_inode's release() call. This helper marks bpf_link as
28192819
* defunct, releases anon_inode file and puts reserved FD. bpf_prog's refcnt
28202820
* is not decremented, it's the responsibility of a calling code that failed
28212821
* to complete bpf_link initialization.
2822+
* This helper eventually calls link's dealloc callback, but does not call
2823+
* link's release callback.
28222824
*/
28232825
void bpf_link_cleanup(struct bpf_link_primer *primer)
28242826
{
@@ -3655,34 +3657,6 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
36553657
return fd;
36563658
}
36573659

3658-
static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
3659-
enum bpf_attach_type attach_type)
3660-
{
3661-
switch (prog->type) {
3662-
case BPF_PROG_TYPE_CGROUP_SOCK:
3663-
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
3664-
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
3665-
case BPF_PROG_TYPE_SK_LOOKUP:
3666-
return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
3667-
case BPF_PROG_TYPE_CGROUP_SKB:
3668-
if (!capable(CAP_NET_ADMIN))
3669-
/* cg-skb progs can be loaded by unpriv user.
3670-
* check permissions at attach time.
3671-
*/
3672-
return -EPERM;
3673-
return prog->enforce_expected_attach_type &&
3674-
prog->expected_attach_type != attach_type ?
3675-
-EINVAL : 0;
3676-
case BPF_PROG_TYPE_KPROBE:
3677-
if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI &&
3678-
attach_type != BPF_TRACE_KPROBE_MULTI)
3679-
return -EINVAL;
3680-
return 0;
3681-
default:
3682-
return 0;
3683-
}
3684-
}
3685-
36863660
static enum bpf_prog_type
36873661
attach_type_to_prog_type(enum bpf_attach_type attach_type)
36883662
{
@@ -3749,6 +3723,62 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
37493723
}
37503724
}
37513725

3726+
static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
3727+
enum bpf_attach_type attach_type)
3728+
{
3729+
enum bpf_prog_type ptype;
3730+
3731+
switch (prog->type) {
3732+
case BPF_PROG_TYPE_CGROUP_SOCK:
3733+
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
3734+
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
3735+
case BPF_PROG_TYPE_SK_LOOKUP:
3736+
return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
3737+
case BPF_PROG_TYPE_CGROUP_SKB:
3738+
if (!capable(CAP_NET_ADMIN))
3739+
/* cg-skb progs can be loaded by unpriv user.
3740+
* check permissions at attach time.
3741+
*/
3742+
return -EPERM;
3743+
return prog->enforce_expected_attach_type &&
3744+
prog->expected_attach_type != attach_type ?
3745+
-EINVAL : 0;
3746+
case BPF_PROG_TYPE_EXT:
3747+
return 0;
3748+
case BPF_PROG_TYPE_NETFILTER:
3749+
if (attach_type != BPF_NETFILTER)
3750+
return -EINVAL;
3751+
return 0;
3752+
case BPF_PROG_TYPE_PERF_EVENT:
3753+
case BPF_PROG_TYPE_TRACEPOINT:
3754+
if (attach_type != BPF_PERF_EVENT)
3755+
return -EINVAL;
3756+
return 0;
3757+
case BPF_PROG_TYPE_KPROBE:
3758+
if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI &&
3759+
attach_type != BPF_TRACE_KPROBE_MULTI)
3760+
return -EINVAL;
3761+
if (prog->expected_attach_type == BPF_TRACE_UPROBE_MULTI &&
3762+
attach_type != BPF_TRACE_UPROBE_MULTI)
3763+
return -EINVAL;
3764+
if (attach_type != BPF_PERF_EVENT &&
3765+
attach_type != BPF_TRACE_KPROBE_MULTI &&
3766+
attach_type != BPF_TRACE_UPROBE_MULTI)
3767+
return -EINVAL;
3768+
return 0;
3769+
case BPF_PROG_TYPE_SCHED_CLS:
3770+
if (attach_type != BPF_TCX_INGRESS &&
3771+
attach_type != BPF_TCX_EGRESS)
3772+
return -EINVAL;
3773+
return 0;
3774+
default:
3775+
ptype = attach_type_to_prog_type(attach_type);
3776+
if (ptype == BPF_PROG_TYPE_UNSPEC || ptype != prog->type)
3777+
return -EINVAL;
3778+
return 0;
3779+
}
3780+
}
3781+
37523782
#define BPF_PROG_ATTACH_LAST_FIELD expected_revision
37533783

37543784
#define BPF_F_ATTACH_MASK_BASE \
@@ -4852,10 +4882,9 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
48524882
return err;
48534883
}
48544884

4855-
#define BPF_LINK_CREATE_LAST_FIELD link_create.kprobe_multi.cookies
4885+
#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.pid
48564886
static int link_create(union bpf_attr *attr, bpfptr_t uattr)
48574887
{
4858-
enum bpf_prog_type ptype;
48594888
struct bpf_prog *prog;
48604889
int ret;
48614890

@@ -4874,45 +4903,6 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
48744903
if (ret)
48754904
goto out;
48764905

4877-
switch (prog->type) {
4878-
case BPF_PROG_TYPE_EXT:
4879-
break;
4880-
case BPF_PROG_TYPE_NETFILTER:
4881-
if (attr->link_create.attach_type != BPF_NETFILTER) {
4882-
ret = -EINVAL;
4883-
goto out;
4884-
}
4885-
break;
4886-
case BPF_PROG_TYPE_PERF_EVENT:
4887-
case BPF_PROG_TYPE_TRACEPOINT:
4888-
if (attr->link_create.attach_type != BPF_PERF_EVENT) {
4889-
ret = -EINVAL;
4890-
goto out;
4891-
}
4892-
break;
4893-
case BPF_PROG_TYPE_KPROBE:
4894-
if (attr->link_create.attach_type != BPF_PERF_EVENT &&
4895-
attr->link_create.attach_type != BPF_TRACE_KPROBE_MULTI) {
4896-
ret = -EINVAL;
4897-
goto out;
4898-
}
4899-
break;
4900-
case BPF_PROG_TYPE_SCHED_CLS:
4901-
if (attr->link_create.attach_type != BPF_TCX_INGRESS &&
4902-
attr->link_create.attach_type != BPF_TCX_EGRESS) {
4903-
ret = -EINVAL;
4904-
goto out;
4905-
}
4906-
break;
4907-
default:
4908-
ptype = attach_type_to_prog_type(attr->link_create.attach_type);
4909-
if (ptype == BPF_PROG_TYPE_UNSPEC || ptype != prog->type) {
4910-
ret = -EINVAL;
4911-
goto out;
4912-
}
4913-
break;
4914-
}
4915-
49164906
switch (prog->type) {
49174907
case BPF_PROG_TYPE_CGROUP_SKB:
49184908
case BPF_PROG_TYPE_CGROUP_SOCK:
@@ -4969,8 +4959,10 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
49694959
case BPF_PROG_TYPE_KPROBE:
49704960
if (attr->link_create.attach_type == BPF_PERF_EVENT)
49714961
ret = bpf_perf_link_attach(attr, prog);
4972-
else
4962+
else if (attr->link_create.attach_type == BPF_TRACE_KPROBE_MULTI)
49734963
ret = bpf_kprobe_multi_link_attach(attr, prog);
4964+
else if (attr->link_create.attach_type == BPF_TRACE_UPROBE_MULTI)
4965+
ret = bpf_uprobe_multi_link_attach(attr, prog);
49744966
break;
49754967
default:
49764968
ret = -EINVAL;

0 commit comments

Comments
 (0)