|
@@ -835,6 +835,77 @@ static int bpf_obj_get(const union bpf_attr *attr)
|
|
|
return bpf_obj_get_user(u64_to_user_ptr(attr->pathname));
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_CGROUP_BPF
|
|
|
+
|
|
|
+#define BPF_PROG_ATTACH_LAST_FIELD attach_type
|
|
|
+
|
|
|
+static int bpf_prog_attach(const union bpf_attr *attr)
|
|
|
+{
|
|
|
+ struct bpf_prog *prog;
|
|
|
+ struct cgroup *cgrp;
|
|
|
+
|
|
|
+ if (!capable(CAP_NET_ADMIN))
|
|
|
+ return -EPERM;
|
|
|
+
|
|
|
+ if (CHECK_ATTR(BPF_PROG_ATTACH))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ switch (attr->attach_type) {
|
|
|
+ case BPF_CGROUP_INET_INGRESS:
|
|
|
+ case BPF_CGROUP_INET_EGRESS:
|
|
|
+ prog = bpf_prog_get_type(attr->attach_bpf_fd,
|
|
|
+ BPF_PROG_TYPE_CGROUP_SKB);
|
|
|
+ if (IS_ERR(prog))
|
|
|
+ return PTR_ERR(prog);
|
|
|
+
|
|
|
+ cgrp = cgroup_get_from_fd(attr->target_fd);
|
|
|
+ if (IS_ERR(cgrp)) {
|
|
|
+ bpf_prog_put(prog);
|
|
|
+ return PTR_ERR(cgrp);
|
|
|
+ }
|
|
|
+
|
|
|
+ cgroup_bpf_update(cgrp, prog, attr->attach_type);
|
|
|
+ cgroup_put(cgrp);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#define BPF_PROG_DETACH_LAST_FIELD attach_type
|
|
|
+
|
|
|
+static int bpf_prog_detach(const union bpf_attr *attr)
|
|
|
+{
|
|
|
+ struct cgroup *cgrp;
|
|
|
+
|
|
|
+ if (!capable(CAP_NET_ADMIN))
|
|
|
+ return -EPERM;
|
|
|
+
|
|
|
+ if (CHECK_ATTR(BPF_PROG_DETACH))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ switch (attr->attach_type) {
|
|
|
+ case BPF_CGROUP_INET_INGRESS:
|
|
|
+ case BPF_CGROUP_INET_EGRESS:
|
|
|
+ cgrp = cgroup_get_from_fd(attr->target_fd);
|
|
|
+ if (IS_ERR(cgrp))
|
|
|
+ return PTR_ERR(cgrp);
|
|
|
+
|
|
|
+ cgroup_bpf_update(cgrp, NULL, attr->attach_type);
|
|
|
+ cgroup_put(cgrp);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif /* CONFIG_CGROUP_BPF */
|
|
|
+
|
|
|
SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
|
|
|
{
|
|
|
union bpf_attr attr = {};
|
|
@@ -901,6 +972,16 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
|
|
|
case BPF_OBJ_GET:
|
|
|
err = bpf_obj_get(&attr);
|
|
|
break;
|
|
|
+
|
|
|
+#ifdef CONFIG_CGROUP_BPF
|
|
|
+ case BPF_PROG_ATTACH:
|
|
|
+ err = bpf_prog_attach(&attr);
|
|
|
+ break;
|
|
|
+ case BPF_PROG_DETACH:
|
|
|
+ err = bpf_prog_detach(&attr);
|
|
|
+ break;
|
|
|
+#endif
|
|
|
+
|
|
|
default:
|
|
|
err = -EINVAL;
|
|
|
break;
|