Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[linux-2.6-microblaze.git] / kernel / bpf / syscall.c
index 0fd80ac..2f343ce 100644 (file)
@@ -1981,6 +1981,7 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
        case BPF_PROG_TYPE_CGROUP_SOCK:
                switch (expected_attach_type) {
                case BPF_CGROUP_INET_SOCK_CREATE:
+               case BPF_CGROUP_INET_SOCK_RELEASE:
                case BPF_CGROUP_INET4_POST_BIND:
                case BPF_CGROUP_INET6_POST_BIND:
                        return 0;
@@ -2021,6 +2022,10 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
                default:
                        return -EINVAL;
                }
+       case BPF_PROG_TYPE_SK_LOOKUP:
+               if (expected_attach_type == BPF_SK_LOOKUP)
+                       return 0;
+               return -EINVAL;
        case BPF_PROG_TYPE_EXT:
                if (expected_attach_type)
                        return -EINVAL;
@@ -2755,6 +2760,7 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
        case BPF_PROG_TYPE_CGROUP_SOCK:
        case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
        case BPF_PROG_TYPE_CGROUP_SOCKOPT:
+       case BPF_PROG_TYPE_SK_LOOKUP:
                return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
        case BPF_PROG_TYPE_CGROUP_SKB:
                if (!capable(CAP_NET_ADMIN))
@@ -2779,6 +2785,7 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
                return BPF_PROG_TYPE_CGROUP_SKB;
                break;
        case BPF_CGROUP_INET_SOCK_CREATE:
+       case BPF_CGROUP_INET_SOCK_RELEASE:
        case BPF_CGROUP_INET4_POST_BIND:
        case BPF_CGROUP_INET6_POST_BIND:
                return BPF_PROG_TYPE_CGROUP_SOCK;
@@ -2815,6 +2822,10 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
                return BPF_PROG_TYPE_CGROUP_SOCKOPT;
        case BPF_TRACE_ITER:
                return BPF_PROG_TYPE_TRACING;
+       case BPF_SK_LOOKUP:
+               return BPF_PROG_TYPE_SK_LOOKUP;
+       case BPF_XDP:
+               return BPF_PROG_TYPE_XDP;
        default:
                return BPF_PROG_TYPE_UNSPEC;
        }
@@ -2927,6 +2938,7 @@ static int bpf_prog_query(const union bpf_attr *attr,
        case BPF_CGROUP_INET_INGRESS:
        case BPF_CGROUP_INET_EGRESS:
        case BPF_CGROUP_INET_SOCK_CREATE:
+       case BPF_CGROUP_INET_SOCK_RELEASE:
        case BPF_CGROUP_INET4_BIND:
        case BPF_CGROUP_INET6_BIND:
        case BPF_CGROUP_INET4_POST_BIND:
@@ -2950,6 +2962,7 @@ static int bpf_prog_query(const union bpf_attr *attr,
        case BPF_LIRC_MODE2:
                return lirc_prog_query(attr, uattr);
        case BPF_FLOW_DISSECTOR:
+       case BPF_SK_LOOKUP:
                return netns_bpf_prog_query(attr, uattr);
        default:
                return -EINVAL;
@@ -3033,6 +3046,25 @@ again:
        return map;
 }
 
+struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id)
+{
+       struct bpf_prog *prog;
+
+       spin_lock_bh(&prog_idr_lock);
+again:
+       prog = idr_get_next(&prog_idr, id);
+       if (prog) {
+               prog = bpf_prog_inc_not_zero(prog);
+               if (IS_ERR(prog)) {
+                       (*id)++;
+                       goto again;
+               }
+       }
+       spin_unlock_bh(&prog_idr_lock);
+
+       return prog;
+}
+
 #define BPF_PROG_GET_FD_BY_ID_LAST_FIELD prog_id
 
 struct bpf_prog *bpf_prog_by_id(u32 id)
@@ -3888,8 +3920,14 @@ static int link_create(union bpf_attr *attr)
                ret = tracing_bpf_link_attach(attr, prog);
                break;
        case BPF_PROG_TYPE_FLOW_DISSECTOR:
+       case BPF_PROG_TYPE_SK_LOOKUP:
                ret = netns_bpf_link_create(attr, prog);
                break;
+#ifdef CONFIG_NET
+       case BPF_PROG_TYPE_XDP:
+               ret = bpf_xdp_link_attach(attr, prog);
+               break;
+#endif
        default:
                ret = -EINVAL;
        }
@@ -3953,6 +3991,29 @@ out_put_link:
        return ret;
 }
 
+#define BPF_LINK_DETACH_LAST_FIELD link_detach.link_fd
+
+static int link_detach(union bpf_attr *attr)
+{
+       struct bpf_link *link;
+       int ret;
+
+       if (CHECK_ATTR(BPF_LINK_DETACH))
+               return -EINVAL;
+
+       link = bpf_link_get_from_fd(attr->link_detach.link_fd);
+       if (IS_ERR(link))
+               return PTR_ERR(link);
+
+       if (link->ops->detach)
+               ret = link->ops->detach(link);
+       else
+               ret = -EOPNOTSUPP;
+
+       bpf_link_put(link);
+       return ret;
+}
+
 static int bpf_link_inc_not_zero(struct bpf_link *link)
 {
        return atomic64_fetch_add_unless(&link->refcnt, 1, 0) ? 0 : -ENOENT;
@@ -4202,6 +4263,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
        case BPF_ITER_CREATE:
                err = bpf_iter_create(&attr);
                break;
+       case BPF_LINK_DETACH:
+               err = link_detach(&attr);
+               break;
        default:
                err = -EINVAL;
                break;