]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - kernel/bpf/syscall.c
bpf: add BPF_PROG_ATTACH and BPF_PROG_DETACH commands
[mirror_ubuntu-artful-kernel.git] / kernel / bpf / syscall.c
index eb15498b8d55c5966397ff10dcdd16adec8dd56d..1090d16a31c154c5557ee99db3ccdbf5fe8ab8b0 100644 (file)
@@ -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;