History

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).

Jiri Olsa committed 3 years ago

Commit b733eea1 parent 0b779b64 files · +36 −1Browse files

Unified · Split

4 files
  1. include/uapi/linux/bpf.h +1 −0
  2. kernel/bpf/syscall.c +1 −1
  3. kernel/trace/bpf_trace.c +33 −0
  4. tools/include/uapi/linux/bpf.h +1 −0
include/uapi/linux/bpf.h+1−0
@@ -1642,6 +1642,7 @@ union bpf_attr { · 1641 unmodified lines
1642 __aligned_u64 cookies;1642 __aligned_u64 cookies;
1643 __u32 cnt;1643 __u32 cnt;
1644 __u32 flags;1644 __u32 flags;
1645 __u32 pid;
1645 } uprobe_multi;1646 } uprobe_multi;
1646 };1647 };
1647 } link_create;1648 } link_create;
kernel/bpf/syscall.c+1−1
@@ -4882,7 +4882,7 @@ err_put: · 4881 unmodified lines
4882 return err;4882 return err;
4883}4883}
4884 4884
4885#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.flags4885#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.pid
4886static int link_create(union bpf_attr *attr, bpfptr_t uattr)4886static int link_create(union bpf_attr *attr, bpfptr_t uattr)
4887{4887{
4888 struct bpf_prog *prog;4888 struct bpf_prog *prog;
kernel/trace/bpf_trace.c+33−0
@@ -3003,6 +3003,7 @@ struct bpf_uprobe_multi_link { · 3002 unmodified lines
3003 struct bpf_link link;3003 struct bpf_link link;
3004 u32 cnt;3004 u32 cnt;
3005 struct bpf_uprobe *uprobes;3005 struct bpf_uprobe *uprobes;
3006 struct task_struct *task;
3006};3007};
3007 3008
3008struct bpf_uprobe_multi_run_ctx {3009struct bpf_uprobe_multi_run_ctx {
@@ -3035,6 +3036,8 @@ static void bpf_uprobe_multi_link_dealloc(struct bpf_link *link) · 26 unmodified lines
3035 struct bpf_uprobe_multi_link *umulti_link;3036 struct bpf_uprobe_multi_link *umulti_link;
3036 3037
3037 umulti_link = container_of(link, struct bpf_uprobe_multi_link, link);3038 umulti_link = container_of(link, struct bpf_uprobe_multi_link, link);
3039 if (umulti_link->task)
3040 put_task_struct(umulti_link->task);
3038 path_put(&umulti_link->path);3041 path_put(&umulti_link->path);
3039 kvfree(umulti_link->uprobes);3042 kvfree(umulti_link->uprobes);
3040 kfree(umulti_link);3043 kfree(umulti_link);
@@ -3059,6 +3062,9 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe, · 18 unmodified lines
3059 struct bpf_run_ctx *old_run_ctx;3062 struct bpf_run_ctx *old_run_ctx;
3060 int err = 0;3063 int err = 0;
3061 3064
3065 if (link->task && current != link->task)
3066 return 0;
3067
3062 if (sleepable)3068 if (sleepable)
3063 rcu_read_lock_trace();3069 rcu_read_lock_trace();
3064 else3070 else
@@ -3079,6 +3085,16 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe, · 14 unmodified lines
3079 return err;3085 return err;
3080}3086}
3081 3087
3088static bool
3089uprobe_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
3082static int3098static int
3083uprobe_multi_link_handler(struct uprobe_consumer *con, struct pt_regs *regs)3099uprobe_multi_link_handler(struct uprobe_consumer *con, struct pt_regs *regs)
3084{3100{
@@ -3112,12 +3128,14 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · 27 unmodified lines
3112 unsigned long *ref_ctr_offsets = NULL;3128 unsigned long *ref_ctr_offsets = NULL;
3113 struct bpf_link_primer link_primer;3129 struct bpf_link_primer link_primer;
3114 struct bpf_uprobe *uprobes = NULL;3130 struct bpf_uprobe *uprobes = NULL;
3131 struct task_struct *task = NULL;
3115 unsigned long __user *uoffsets;3132 unsigned long __user *uoffsets;
3116 u64 __user *ucookies;3133 u64 __user *ucookies;
3117 void __user *upath;3134 void __user *upath;
3118 u32 flags, cnt, i;3135 u32 flags, cnt, i;
3119 struct path path;3136 struct path path;
3120 char *name;3137 char *name;
3138 pid_t pid;
3121 int err;3139 int err;
3122 3140
3123 /* no support for 32bit archs yet */3141 /* 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 · 37 unmodified lines
3161 goto error_path_put;3179 goto error_path_put;
3162 }3180 }
3163 3181
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
3164 err = -ENOMEM;3191 err = -ENOMEM;
3165 3192
3166 link = kzalloc(sizeof(*link), GFP_KERNEL);3193 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 · 28 unmodified lines
3195 uprobes[i].consumer.ret_handler = uprobe_multi_link_ret_handler;3222 uprobes[i].consumer.ret_handler = uprobe_multi_link_ret_handler;
3196 else3223 else
3197 uprobes[i].consumer.handler = uprobe_multi_link_handler;3224 uprobes[i].consumer.handler = uprobe_multi_link_handler;
3225
3226 if (pid)
3227 uprobes[i].consumer.filter = uprobe_multi_link_filter;
3198 }3228 }
3199 3229
3200 link->cnt = cnt;3230 link->cnt = cnt;
3201 link->uprobes = uprobes;3231 link->uprobes = uprobes;
3202 link->path = path;3232 link->path = path;
3233 link->task = task;
3203 3234
3204 bpf_link_init(&link->link, BPF_LINK_TYPE_UPROBE_MULTI,3235 bpf_link_init(&link->link, BPF_LINK_TYPE_UPROBE_MULTI,
3205 &bpf_uprobe_multi_link_lops, prog);3236 &bpf_uprobe_multi_link_lops, prog);
@@ -3226,6 +3257,8 @@ error_free: · 20 unmodified lines
3226 kvfree(ref_ctr_offsets);3257 kvfree(ref_ctr_offsets);
3227 kvfree(uprobes);3258 kvfree(uprobes);
3228 kfree(link);3259 kfree(link);
3260 if (task)
3261 put_task_struct(task);
3229error_path_put:3262error_path_put:
3230 path_put(&path);3263 path_put(&path);
3231 return err;3264 return err;
tools/include/uapi/linux/bpf.h+1−0
@@ -1642,6 +1642,7 @@ union bpf_attr { · 1641 unmodified lines
1642 __aligned_u64 cookies;1642 __aligned_u64 cookies;
1643 __u32 cnt;1643 __u32 cnt;
1644 __u32 flags;1644 __u32 flags;
1645 __u32 pid;
1645 } uprobe_multi;1646 } uprobe_multi;
1646 };1647 };
1647 } link_create;1648 } link_create;