Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[sfrench/cifs-2.6.git] / kernel / bpf / cgroup.c
index 59b7eb60d5b46a05dfba0ce598f3dad53aa9863e..00c7f864900e6b8966264c65b96a6a7f6c8b81d4 100644 (file)
@@ -921,8 +921,10 @@ static void purge_effective_progs(struct cgroup *cgrp, struct bpf_prog *prog,
                                pos++;
                        }
                }
+
+               /* no link or prog match, skip the cgroup of this layer */
+               continue;
 found:
-               BUG_ON(!cg);
                progs = rcu_dereference_protected(
                                desc->bpf.effective[atype],
                                lockdep_is_held(&cgroup_mutex));
@@ -1527,6 +1529,37 @@ int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor,
        return ret;
 }
 
+BPF_CALL_2(bpf_get_local_storage, struct bpf_map *, map, u64, flags)
+{
+       /* flags argument is not used now,
+        * but provides an ability to extend the API.
+        * verifier checks that its value is correct.
+        */
+       enum bpf_cgroup_storage_type stype = cgroup_storage_type(map);
+       struct bpf_cgroup_storage *storage;
+       struct bpf_cg_run_ctx *ctx;
+       void *ptr;
+
+       /* get current cgroup storage from BPF run context */
+       ctx = container_of(current->bpf_ctx, struct bpf_cg_run_ctx, run_ctx);
+       storage = ctx->prog_item->cgroup_storage[stype];
+
+       if (stype == BPF_CGROUP_STORAGE_SHARED)
+               ptr = &READ_ONCE(storage->buf)->data[0];
+       else
+               ptr = this_cpu_ptr(storage->percpu_buf);
+
+       return (unsigned long)ptr;
+}
+
+const struct bpf_func_proto bpf_get_local_storage_proto = {
+       .func           = bpf_get_local_storage,
+       .gpl_only       = false,
+       .ret_type       = RET_PTR_TO_MAP_VALUE,
+       .arg1_type      = ARG_CONST_MAP_PTR,
+       .arg2_type      = ARG_ANYTHING,
+};
+
 BPF_CALL_0(bpf_get_retval)
 {
        struct bpf_cg_run_ctx *ctx =
@@ -1558,32 +1591,26 @@ const struct bpf_func_proto bpf_set_retval_proto = {
 };
 
 static const struct bpf_func_proto *
-cgroup_base_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
+cgroup_dev_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
+       const struct bpf_func_proto *func_proto;
+
+       func_proto = cgroup_common_func_proto(func_id, prog);
+       if (func_proto)
+               return func_proto;
+
+       func_proto = cgroup_current_func_proto(func_id, prog);
+       if (func_proto)
+               return func_proto;
+
        switch (func_id) {
-       case BPF_FUNC_get_current_uid_gid:
-               return &bpf_get_current_uid_gid_proto;
-       case BPF_FUNC_get_local_storage:
-               return &bpf_get_local_storage_proto;
-       case BPF_FUNC_get_current_cgroup_id:
-               return &bpf_get_current_cgroup_id_proto;
        case BPF_FUNC_perf_event_output:
                return &bpf_event_output_data_proto;
-       case BPF_FUNC_get_retval:
-               return &bpf_get_retval_proto;
-       case BPF_FUNC_set_retval:
-               return &bpf_set_retval_proto;
        default:
                return bpf_base_func_proto(func_id);
        }
 }
 
-static const struct bpf_func_proto *
-cgroup_dev_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
-{
-       return cgroup_base_func_proto(func_id, prog);
-}
-
 static bool cgroup_dev_is_valid_access(int off, int size,
                                       enum bpf_access_type type,
                                       const struct bpf_prog *prog,
@@ -2096,11 +2123,17 @@ static const struct bpf_func_proto bpf_sysctl_set_new_value_proto = {
 static const struct bpf_func_proto *
 sysctl_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
+       const struct bpf_func_proto *func_proto;
+
+       func_proto = cgroup_common_func_proto(func_id, prog);
+       if (func_proto)
+               return func_proto;
+
+       func_proto = cgroup_current_func_proto(func_id, prog);
+       if (func_proto)
+               return func_proto;
+
        switch (func_id) {
-       case BPF_FUNC_strtol:
-               return &bpf_strtol_proto;
-       case BPF_FUNC_strtoul:
-               return &bpf_strtoul_proto;
        case BPF_FUNC_sysctl_get_name:
                return &bpf_sysctl_get_name_proto;
        case BPF_FUNC_sysctl_get_current_value:
@@ -2111,8 +2144,10 @@ sysctl_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_sysctl_set_new_value_proto;
        case BPF_FUNC_ktime_get_coarse_ns:
                return &bpf_ktime_get_coarse_ns_proto;
+       case BPF_FUNC_perf_event_output:
+               return &bpf_event_output_data_proto;
        default:
-               return cgroup_base_func_proto(func_id, prog);
+               return bpf_base_func_proto(func_id);
        }
 }
 
@@ -2233,6 +2268,16 @@ static const struct bpf_func_proto bpf_get_netns_cookie_sockopt_proto = {
 static const struct bpf_func_proto *
 cg_sockopt_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
+       const struct bpf_func_proto *func_proto;
+
+       func_proto = cgroup_common_func_proto(func_id, prog);
+       if (func_proto)
+               return func_proto;
+
+       func_proto = cgroup_current_func_proto(func_id, prog);
+       if (func_proto)
+               return func_proto;
+
        switch (func_id) {
 #ifdef CONFIG_NET
        case BPF_FUNC_get_netns_cookie:
@@ -2254,8 +2299,10 @@ cg_sockopt_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        case BPF_FUNC_tcp_sock:
                return &bpf_tcp_sock_proto;
 #endif
+       case BPF_FUNC_perf_event_output:
+               return &bpf_event_output_data_proto;
        default:
-               return cgroup_base_func_proto(func_id, prog);
+               return bpf_base_func_proto(func_id);
        }
 }
 
@@ -2420,3 +2467,69 @@ const struct bpf_verifier_ops cg_sockopt_verifier_ops = {
 
 const struct bpf_prog_ops cg_sockopt_prog_ops = {
 };
+
+/* Common helpers for cgroup hooks. */
+const struct bpf_func_proto *
+cgroup_common_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
+{
+       switch (func_id) {
+       case BPF_FUNC_get_local_storage:
+               return &bpf_get_local_storage_proto;
+       case BPF_FUNC_get_retval:
+               switch (prog->expected_attach_type) {
+               case BPF_CGROUP_INET_INGRESS:
+               case BPF_CGROUP_INET_EGRESS:
+               case BPF_CGROUP_SOCK_OPS:
+               case BPF_CGROUP_UDP4_RECVMSG:
+               case BPF_CGROUP_UDP6_RECVMSG:
+               case BPF_CGROUP_INET4_GETPEERNAME:
+               case BPF_CGROUP_INET6_GETPEERNAME:
+               case BPF_CGROUP_INET4_GETSOCKNAME:
+               case BPF_CGROUP_INET6_GETSOCKNAME:
+                       return NULL;
+               default:
+                       return &bpf_get_retval_proto;
+               }
+       case BPF_FUNC_set_retval:
+               switch (prog->expected_attach_type) {
+               case BPF_CGROUP_INET_INGRESS:
+               case BPF_CGROUP_INET_EGRESS:
+               case BPF_CGROUP_SOCK_OPS:
+               case BPF_CGROUP_UDP4_RECVMSG:
+               case BPF_CGROUP_UDP6_RECVMSG:
+               case BPF_CGROUP_INET4_GETPEERNAME:
+               case BPF_CGROUP_INET6_GETPEERNAME:
+               case BPF_CGROUP_INET4_GETSOCKNAME:
+               case BPF_CGROUP_INET6_GETSOCKNAME:
+                       return NULL;
+               default:
+                       return &bpf_set_retval_proto;
+               }
+       default:
+               return NULL;
+       }
+}
+
+/* Common helpers for cgroup hooks with valid process context. */
+const struct bpf_func_proto *
+cgroup_current_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
+{
+       switch (func_id) {
+       case BPF_FUNC_get_current_uid_gid:
+               return &bpf_get_current_uid_gid_proto;
+       case BPF_FUNC_get_current_pid_tgid:
+               return &bpf_get_current_pid_tgid_proto;
+       case BPF_FUNC_get_current_comm:
+               return &bpf_get_current_comm_proto;
+       case BPF_FUNC_get_current_cgroup_id:
+               return &bpf_get_current_cgroup_id_proto;
+       case BPF_FUNC_get_current_ancestor_cgroup_id:
+               return &bpf_get_current_ancestor_cgroup_id_proto;
+#ifdef CONFIG_CGROUP_NET_CLASSID
+       case BPF_FUNC_get_cgroup_classid:
+               return &bpf_get_cgroup_classid_curr_proto;
+#endif
+       default:
+               return NULL;
+       }
+}