Using BPF_PROG_DETACH on a flow dissector program supports neither attach_flags nor attach_bpf_fd. Yet no value is enforced for them. Enforce that attach_flags are zero, and require the current program to be passed via attach_bpf_fd. This allows us to remove the check for CAP_SYS_ADMIN, since userspace can now no longer remove arbitrary flow dissector programs.
Unified · Split
| @@ -33,7 +33,7 @@ int netns_bpf_prog_query(const union bpf_attr *attr, · 32 unmodified lines | |||
| 33 | union bpf_attr __user *uattr); | 33 | union bpf_attr __user *uattr); |
| 34 | int netns_bpf_prog_attach(const union bpf_attr *attr, | 34 | int netns_bpf_prog_attach(const union bpf_attr *attr, |
| 35 | struct bpf_prog *prog); | 35 | struct bpf_prog *prog); |
| 36 | int netns_bpf_prog_detach(const union bpf_attr *attr); | 36 | int netns_bpf_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype); |
| 37 | int netns_bpf_link_create(const union bpf_attr *attr, | 37 | int netns_bpf_link_create(const union bpf_attr *attr, |
| 38 | struct bpf_prog *prog); | 38 | struct bpf_prog *prog); |
| 39 | #else | 39 | #else |
| @@ -49,7 +49,8 @@ static inline int netns_bpf_prog_attach(const union bpf_attr *attr, · 9 unmodified lines | |||
| 49 | return -EOPNOTSUPP; | 49 | return -EOPNOTSUPP; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | static inline int netns_bpf_prog_detach(const union bpf_attr *attr) | 52 | static inline int netns_bpf_prog_detach(const union bpf_attr *attr, |
| 53 | enum bpf_prog_type ptype) | ||
| 53 | { | 54 | { |
| 54 | return -EOPNOTSUPP; | 55 | return -EOPNOTSUPP; |
| 55 | } | 56 | } |
| @@ -269,7 +269,8 @@ out_unlock: · 268 unmodified lines | |||
| 269 | 269 | ||
| 270 | /* Must be called with netns_bpf_mutex held. */ | 270 | /* Must be called with netns_bpf_mutex held. */ |
| 271 | static int __netns_bpf_prog_detach(struct net *net, | 271 | static int __netns_bpf_prog_detach(struct net *net, |
| 272 | enum netns_bpf_attach_type type) | 272 | enum netns_bpf_attach_type type, |
| 273 | struct bpf_prog *old) | ||
| 273 | { | 274 | { |
| 274 | struct bpf_prog *attached; | 275 | struct bpf_prog *attached; |
| 275 | 276 | ||
| @@ -278,7 +279,7 @@ static int __netns_bpf_prog_detach(struct net *net, · 2 unmodified lines | |||
| 278 | return -EINVAL; | 279 | return -EINVAL; |
| 279 | 280 | ||
| 280 | attached = net->bpf.progs[type]; | 281 | attached = net->bpf.progs[type]; |
| 281 | if (!attached) | 282 | if (!attached || attached != old) |
| 282 | return -ENOENT; | 283 | return -ENOENT; |
| 283 | netns_bpf_run_array_detach(net, type); | 284 | netns_bpf_run_array_detach(net, type); |
| 284 | net->bpf.progs[type] = NULL; | 285 | net->bpf.progs[type] = NULL; |
| @@ -286,19 +287,29 @@ static int __netns_bpf_prog_detach(struct net *net, · 1 unmodified line | |||
| 286 | return 0; | 287 | return 0; |
| 287 | } | 288 | } |
| 288 | 289 | ||
| 289 | int netns_bpf_prog_detach(const union bpf_attr *attr) | 290 | int netns_bpf_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype) |
| 290 | { | 291 | { |
| 291 | enum netns_bpf_attach_type type; | 292 | enum netns_bpf_attach_type type; |
| 293 | struct bpf_prog *prog; | ||
| 292 | int ret; | 294 | int ret; |
| 293 | 295 | ||
| 296 | if (attr->target_fd) | ||
| 297 | return -EINVAL; | ||
| 298 | |||
| 294 | type = to_netns_bpf_attach_type(attr->attach_type); | 299 | type = to_netns_bpf_attach_type(attr->attach_type); |
| 295 | if (type < 0) | 300 | if (type < 0) |
| 296 | return -EINVAL; | 301 | return -EINVAL; |
| 297 | 302 | ||
| 303 | prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype); | ||
| 304 | if (IS_ERR(prog)) | ||
| 305 | return PTR_ERR(prog); | ||
| 306 | |||
| 298 | mutex_lock(&netns_bpf_mutex); | 307 | mutex_lock(&netns_bpf_mutex); |
| 299 | ret = __netns_bpf_prog_detach(current->nsproxy->net_ns, type); | 308 | ret = __netns_bpf_prog_detach(current->nsproxy->net_ns, type, prog); |
| 300 | mutex_unlock(&netns_bpf_mutex); | 309 | mutex_unlock(&netns_bpf_mutex); |
| 301 | 310 | ||
| 311 | bpf_prog_put(prog); | ||
| 312 | |||
| 302 | return ret; | 313 | return ret; |
| 303 | } | 314 | } |
| 304 | 315 | ||
| @@ -2897,9 +2897,7 @@ static int bpf_prog_detach(const union bpf_attr *attr) · 2896 unmodified lines | |||
| 2897 | case BPF_PROG_TYPE_LIRC_MODE2: | 2897 | case BPF_PROG_TYPE_LIRC_MODE2: |
| 2898 | return lirc_prog_detach(attr); | 2898 | return lirc_prog_detach(attr); |
| 2899 | case BPF_PROG_TYPE_FLOW_DISSECTOR: | 2899 | case BPF_PROG_TYPE_FLOW_DISSECTOR: |
| 2900 | if (!capable(CAP_NET_ADMIN)) | 2900 | return netns_bpf_prog_detach(attr, ptype); |
| 2901 | return -EPERM; | ||
| 2902 | return netns_bpf_prog_detach(attr); | ||
| 2903 | case BPF_PROG_TYPE_CGROUP_DEVICE: | 2901 | case BPF_PROG_TYPE_CGROUP_DEVICE: |
| 2904 | case BPF_PROG_TYPE_CGROUP_SKB: | 2902 | case BPF_PROG_TYPE_CGROUP_SKB: |
| 2905 | case BPF_PROG_TYPE_CGROUP_SOCK: | 2903 | case BPF_PROG_TYPE_CGROUP_SOCK: |