Skip to content

Commit b733eea

Browse files
olsajiriAlexei Starovoitov
authored andcommitted
bpf: Add pid filter support for uprobe_multi link
Adding support to specify pid for uprobe_multi link and the uprobes are created only for task with given pid value. Using the consumer.filter filter callback for that, so the task gets filtered during the uprobe installation. We still need to check the task during runtime in the uprobe handler, because the handler could get executed if there's another system wide consumer on the same uprobe (thanks Oleg for the insight). Cc: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Jiri Olsa <jolsa@kernel.org> Acked-by: Yonghong Song <yonghong.song@linux.dev> Link: https://lore.kernel.org/r/20230809083440.3209381-6-jolsa@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 0b779b6 commit b733eea

4 files changed

Lines changed: 36 additions & 1 deletion

File tree

include/uapi/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,7 @@ union bpf_attr {
16421642
__aligned_u64 cookies;
16431643
__u32 cnt;
16441644
__u32 flags;
1645+
__u32 pid;
16451646
} uprobe_multi;
16461647
};
16471648
} link_create;

kernel/bpf/syscall.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4882,7 +4882,7 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
48824882
return err;
48834883
}
48844884

4885-
#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.flags
4885+
#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.pid
48864886
static int link_create(union bpf_attr *attr, bpfptr_t uattr)
48874887
{
48884888
struct bpf_prog *prog;

kernel/trace/bpf_trace.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3003,6 +3003,7 @@ struct bpf_uprobe_multi_link {
30033003
struct bpf_link link;
30043004
u32 cnt;
30053005
struct bpf_uprobe *uprobes;
3006+
struct task_struct *task;
30063007
};
30073008

30083009
struct bpf_uprobe_multi_run_ctx {
@@ -3035,6 +3036,8 @@ static void bpf_uprobe_multi_link_dealloc(struct bpf_link *link)
30353036
struct bpf_uprobe_multi_link *umulti_link;
30363037

30373038
umulti_link = container_of(link, struct bpf_uprobe_multi_link, link);
3039+
if (umulti_link->task)
3040+
put_task_struct(umulti_link->task);
30383041
path_put(&umulti_link->path);
30393042
kvfree(umulti_link->uprobes);
30403043
kfree(umulti_link);
@@ -3059,6 +3062,9 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe,
30593062
struct bpf_run_ctx *old_run_ctx;
30603063
int err = 0;
30613064

3065+
if (link->task && current != link->task)
3066+
return 0;
3067+
30623068
if (sleepable)
30633069
rcu_read_lock_trace();
30643070
else
@@ -3079,6 +3085,16 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe,
30793085
return err;
30803086
}
30813087

3088+
static bool
3089+
uprobe_multi_link_filter(struct uprobe_consumer *con, enum uprobe_filter_ctx ctx,
3090+
struct mm_struct *mm)
3091+
{
3092+
struct bpf_uprobe *uprobe;
3093+
3094+
uprobe = container_of(con, struct bpf_uprobe, consumer);
3095+
return uprobe->link->task->mm == mm;
3096+
}
3097+
30823098
static int
30833099
uprobe_multi_link_handler(struct uprobe_consumer *con, struct pt_regs *regs)
30843100
{
@@ -3112,12 +3128,14 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
31123128
unsigned long *ref_ctr_offsets = NULL;
31133129
struct bpf_link_primer link_primer;
31143130
struct bpf_uprobe *uprobes = NULL;
3131+
struct task_struct *task = NULL;
31153132
unsigned long __user *uoffsets;
31163133
u64 __user *ucookies;
31173134
void __user *upath;
31183135
u32 flags, cnt, i;
31193136
struct path path;
31203137
char *name;
3138+
pid_t pid;
31213139
int err;
31223140

31233141
/* no support for 32bit archs yet */
@@ -3161,6 +3179,15 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
31613179
goto error_path_put;
31623180
}
31633181

3182+
pid = attr->link_create.uprobe_multi.pid;
3183+
if (pid) {
3184+
rcu_read_lock();
3185+
task = get_pid_task(find_vpid(pid), PIDTYPE_PID);
3186+
rcu_read_unlock();
3187+
if (!task)
3188+
goto error_path_put;
3189+
}
3190+
31643191
err = -ENOMEM;
31653192

31663193
link = kzalloc(sizeof(*link), GFP_KERNEL);
@@ -3195,11 +3222,15 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
31953222
uprobes[i].consumer.ret_handler = uprobe_multi_link_ret_handler;
31963223
else
31973224
uprobes[i].consumer.handler = uprobe_multi_link_handler;
3225+
3226+
if (pid)
3227+
uprobes[i].consumer.filter = uprobe_multi_link_filter;
31983228
}
31993229

32003230
link->cnt = cnt;
32013231
link->uprobes = uprobes;
32023232
link->path = path;
3233+
link->task = task;
32033234

32043235
bpf_link_init(&link->link, BPF_LINK_TYPE_UPROBE_MULTI,
32053236
&bpf_uprobe_multi_link_lops, prog);
@@ -3226,6 +3257,8 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
32263257
kvfree(ref_ctr_offsets);
32273258
kvfree(uprobes);
32283259
kfree(link);
3260+
if (task)
3261+
put_task_struct(task);
32293262
error_path_put:
32303263
path_put(&path);
32313264
return err;

tools/include/uapi/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,7 @@ union bpf_attr {
16421642
__aligned_u64 cookies;
16431643
__u32 cnt;
16441644
__u32 flags;
1645+
__u32 pid;
16451646
} uprobe_multi;
16461647
};
16471648
} link_create;

0 commit comments

Comments
 (0)