bpf: Post-hooks for sys_bind
[muen/linux.git] / kernel / bpf / syscall.c
index cf1b29bc0ab87125499777372c7cd1d5067a6acb..0244973ee54496cea3935e98e1325aac8d3d6cb7 100644 (file)
@@ -1171,11 +1171,46 @@ struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type,
 }
 EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev);
 
 }
 EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev);
 
+/* Initially all BPF programs could be loaded w/o specifying
+ * expected_attach_type. Later for some of them specifying expected_attach_type
+ * at load time became required so that program could be validated properly.
+ * Programs of types that are allowed to be loaded both w/ and w/o (for
+ * backward compatibility) expected_attach_type, should have the default attach
+ * type assigned to expected_attach_type for the latter case, so that it can be
+ * validated later at attach time.
+ *
+ * bpf_prog_load_fixup_attach_type() sets expected_attach_type in @attr if
+ * prog type requires it but has some attach types that have to be backward
+ * compatible.
+ */
+static void bpf_prog_load_fixup_attach_type(union bpf_attr *attr)
+{
+       switch (attr->prog_type) {
+       case BPF_PROG_TYPE_CGROUP_SOCK:
+               /* Unfortunately BPF_ATTACH_TYPE_UNSPEC enumeration doesn't
+                * exist so checking for non-zero is the way to go here.
+                */
+               if (!attr->expected_attach_type)
+                       attr->expected_attach_type =
+                               BPF_CGROUP_INET_SOCK_CREATE;
+               break;
+       }
+}
+
 static int
 bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type,
                                enum bpf_attach_type expected_attach_type)
 {
        switch (prog_type) {
 static int
 bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type,
                                enum bpf_attach_type expected_attach_type)
 {
        switch (prog_type) {
+       case BPF_PROG_TYPE_CGROUP_SOCK:
+               switch (expected_attach_type) {
+               case BPF_CGROUP_INET_SOCK_CREATE:
+               case BPF_CGROUP_INET4_POST_BIND:
+               case BPF_CGROUP_INET6_POST_BIND:
+                       return 0;
+               default:
+                       return -EINVAL;
+               }
        case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
                switch (expected_attach_type) {
                case BPF_CGROUP_INET4_BIND:
        case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
                switch (expected_attach_type) {
                case BPF_CGROUP_INET4_BIND:
@@ -1195,6 +1230,7 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
                                             enum bpf_attach_type attach_type)
 {
        switch (prog->type) {
                                             enum bpf_attach_type attach_type)
 {
        switch (prog->type) {
+       case BPF_PROG_TYPE_CGROUP_SOCK:
        case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
                return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
        default:
        case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
                return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
        default:
@@ -1240,6 +1276,7 @@ static int bpf_prog_load(union bpf_attr *attr)
            !capable(CAP_SYS_ADMIN))
                return -EPERM;
 
            !capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       bpf_prog_load_fixup_attach_type(attr);
        if (bpf_prog_load_check_attach_type(type, attr->expected_attach_type))
                return -EINVAL;
 
        if (bpf_prog_load_check_attach_type(type, attr->expected_attach_type))
                return -EINVAL;
 
@@ -1489,6 +1526,8 @@ static int bpf_prog_attach(const union bpf_attr *attr)
                ptype = BPF_PROG_TYPE_CGROUP_SKB;
                break;
        case BPF_CGROUP_INET_SOCK_CREATE:
                ptype = BPF_PROG_TYPE_CGROUP_SKB;
                break;
        case BPF_CGROUP_INET_SOCK_CREATE:
+       case BPF_CGROUP_INET4_POST_BIND:
+       case BPF_CGROUP_INET6_POST_BIND:
                ptype = BPF_PROG_TYPE_CGROUP_SOCK;
                break;
        case BPF_CGROUP_INET4_BIND:
                ptype = BPF_PROG_TYPE_CGROUP_SOCK;
                break;
        case BPF_CGROUP_INET4_BIND:
@@ -1557,6 +1596,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
                ptype = BPF_PROG_TYPE_CGROUP_SKB;
                break;
        case BPF_CGROUP_INET_SOCK_CREATE:
                ptype = BPF_PROG_TYPE_CGROUP_SKB;
                break;
        case BPF_CGROUP_INET_SOCK_CREATE:
+       case BPF_CGROUP_INET4_POST_BIND:
+       case BPF_CGROUP_INET6_POST_BIND:
                ptype = BPF_PROG_TYPE_CGROUP_SOCK;
                break;
        case BPF_CGROUP_INET4_BIND:
                ptype = BPF_PROG_TYPE_CGROUP_SOCK;
                break;
        case BPF_CGROUP_INET4_BIND:
@@ -1616,6 +1657,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
        case BPF_CGROUP_INET_SOCK_CREATE:
        case BPF_CGROUP_INET4_BIND:
        case BPF_CGROUP_INET6_BIND:
        case BPF_CGROUP_INET_SOCK_CREATE:
        case BPF_CGROUP_INET4_BIND:
        case BPF_CGROUP_INET6_BIND:
+       case BPF_CGROUP_INET4_POST_BIND:
+       case BPF_CGROUP_INET6_POST_BIND:
        case BPF_CGROUP_INET4_CONNECT:
        case BPF_CGROUP_INET6_CONNECT:
        case BPF_CGROUP_SOCK_OPS:
        case BPF_CGROUP_INET4_CONNECT:
        case BPF_CGROUP_INET6_CONNECT:
        case BPF_CGROUP_SOCK_OPS: