| @@ -3042,6 +3042,7 @@ struct bpf_uprobe_multi_link { · 3041 unmodified lines |
| 3042 | struct path path; | 3042 | struct path path; |
| 3043 | struct bpf_link link; | 3043 | struct bpf_link link; |
| 3044 | u32 cnt; | 3044 | u32 cnt; |
| | 3045 | u32 flags; |
| 3045 | struct bpf_uprobe *uprobes; | 3046 | struct bpf_uprobe *uprobes; |
| 3046 | struct task_struct *task; | 3047 | struct task_struct *task; |
| 3047 | }; | 3048 | }; |
| @@ -3083,9 +3084,79 @@ static void bpf_uprobe_multi_link_dealloc(struct bpf_link *link) · 35 unmodified lines |
| 3083 | kfree(umulti_link); | 3084 | kfree(umulti_link); |
| 3084 | } | 3085 | } |
| 3085 | | 3086 | |
| | 3087 | static int bpf_uprobe_multi_link_fill_link_info(const struct bpf_link *link, |
| | 3088 | struct bpf_link_info *info) |
| | 3089 | { |
| | 3090 | u64 __user *uref_ctr_offsets = u64_to_user_ptr(info->uprobe_multi.ref_ctr_offsets); |
| | 3091 | u64 __user *ucookies = u64_to_user_ptr(info->uprobe_multi.cookies); |
| | 3092 | u64 __user *uoffsets = u64_to_user_ptr(info->uprobe_multi.offsets); |
| | 3093 | u64 __user *upath = u64_to_user_ptr(info->uprobe_multi.path); |
| | 3094 | u32 upath_size = info->uprobe_multi.path_size; |
| | 3095 | struct bpf_uprobe_multi_link *umulti_link; |
| | 3096 | u32 ucount = info->uprobe_multi.count; |
| | 3097 | int err = 0, i; |
| | 3098 | long left; |
| | 3099 | |
| | 3100 | if (!upath ^ !upath_size) |
| | 3101 | return -EINVAL; |
| | 3102 | |
| | 3103 | if ((uoffsets || uref_ctr_offsets || ucookies) && !ucount) |
| | 3104 | return -EINVAL; |
| | 3105 | |
| | 3106 | umulti_link = container_of(link, struct bpf_uprobe_multi_link, link); |
| | 3107 | info->uprobe_multi.count = umulti_link->cnt; |
| | 3108 | info->uprobe_multi.flags = umulti_link->flags; |
| | 3109 | info->uprobe_multi.pid = umulti_link->task ? |
| | 3110 | task_pid_nr_ns(umulti_link->task, task_active_pid_ns(current)) : 0; |
| | 3111 | |
| | 3112 | if (upath) { |
| | 3113 | char *p, *buf; |
| | 3114 | |
| | 3115 | upath_size = min_t(u32, upath_size, PATH_MAX); |
| | 3116 | |
| | 3117 | buf = kmalloc(upath_size, GFP_KERNEL); |
| | 3118 | if (!buf) |
| | 3119 | return -ENOMEM; |
| | 3120 | p = d_path(&umulti_link->path, buf, upath_size); |
| | 3121 | if (IS_ERR(p)) { |
| | 3122 | kfree(buf); |
| | 3123 | return PTR_ERR(p); |
| | 3124 | } |
| | 3125 | upath_size = buf + upath_size - p; |
| | 3126 | left = copy_to_user(upath, p, upath_size); |
| | 3127 | kfree(buf); |
| | 3128 | if (left) |
| | 3129 | return -EFAULT; |
| | 3130 | info->uprobe_multi.path_size = upath_size; |
| | 3131 | } |
| | 3132 | |
| | 3133 | if (!uoffsets && !ucookies && !uref_ctr_offsets) |
| | 3134 | return 0; |
| | 3135 | |
| | 3136 | if (ucount < umulti_link->cnt) |
| | 3137 | err = -ENOSPC; |
| | 3138 | else |
| | 3139 | ucount = umulti_link->cnt; |
| | 3140 | |
| | 3141 | for (i = 0; i < ucount; i++) { |
| | 3142 | if (uoffsets && |
| | 3143 | put_user(umulti_link->uprobes[i].offset, uoffsets + i)) |
| | 3144 | return -EFAULT; |
| | 3145 | if (uref_ctr_offsets && |
| | 3146 | put_user(umulti_link->uprobes[i].ref_ctr_offset, uref_ctr_offsets + i)) |
| | 3147 | return -EFAULT; |
| | 3148 | if (ucookies && |
| | 3149 | put_user(umulti_link->uprobes[i].cookie, ucookies + i)) |
| | 3150 | return -EFAULT; |
| | 3151 | } |
| | 3152 | |
| | 3153 | return err; |
| | 3154 | } |
| | 3155 | |
| 3086 | static const struct bpf_link_ops bpf_uprobe_multi_link_lops = { | 3156 | static const struct bpf_link_ops bpf_uprobe_multi_link_lops = { |
| 3087 | .release = bpf_uprobe_multi_link_release, | 3157 | .release = bpf_uprobe_multi_link_release, |
| 3088 | .dealloc = bpf_uprobe_multi_link_dealloc, | 3158 | .dealloc = bpf_uprobe_multi_link_dealloc, |
| | 3159 | .fill_link_info = bpf_uprobe_multi_link_fill_link_info, |
| 3089 | }; | 3160 | }; |
| 3090 | | 3161 | |
| 3091 | static int uprobe_prog_run(struct bpf_uprobe *uprobe, | 3162 | static int uprobe_prog_run(struct bpf_uprobe *uprobe, |
| @@ -3274,6 +3345,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · 182 unmodified lines |
| 3274 | link->uprobes = uprobes; | 3345 | link->uprobes = uprobes; |
| 3275 | link->path = path; | 3346 | link->path = path; |
| 3276 | link->task = task; | 3347 | link->task = task; |
| | 3348 | link->flags = flags; |
| 3277 | | 3349 | |
| 3278 | bpf_link_init(&link->link, BPF_LINK_TYPE_UPROBE_MULTI, | 3350 | bpf_link_init(&link->link, BPF_LINK_TYPE_UPROBE_MULTI, |
| 3279 | &bpf_uprobe_multi_link_lops, prog); | 3351 | &bpf_uprobe_multi_link_lops, prog); |