summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-07-01 16:32:27 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-01 16:32:27 -0400
commitdc9a20020a73e81766f1a6341bcafb7f00b5f92a (patch)
treece74217c60eeda9e99a8b5e2babcf0847ab3b24f /net
parent6bd3847bdc3ba97e642cb9af9d16b0f056da31a2 (diff)
parenta3f74617340b598dbc7eb5b68d4ed53b4a70f5eb (diff)
Merge branch 'bpf-cgroup2'
Martin KaFai Lau says: ==================== cgroup: bpf: cgroup2 membership test on skb This series is to implement a bpf-way to check the cgroup2 membership of a skb (sk_buff). It is similar to the feature added in netfilter: c38c4597e4bf ("netfilter: implement xt_cgroup cgroup2 path match") The current target is the tc-like usage. v3: - Remove WARN_ON_ONCE(!rcu_read_lock_held()) - Stop BPF_MAP_TYPE_CGROUP_ARRAY usage in patch 2/4 - Avoid mounting bpf fs manually in patch 4/4 - Thanks for Daniel's review and the above suggestions - Check CONFIG_SOCK_CGROUP_DATA instead of CONFIG_CGROUPS. Thanks to the kbuild bot's report. Patch 2/4 only needs CONFIG_CGROUPS while patch 3/4 needs CONFIG_SOCK_CGROUP_DATA. Since a single bpf cgrp2 array alone is not useful for now, CONFIG_SOCK_CGROUP_DATA is also used in patch 2/4. We can fine tune it later if we find other use cases for the cgrp2 array. - Return EAGAIN instead of ENOENT if the cgrp2 array entry is NULL. It is to distinguish these two cases: 1) the userland has not populated this array entry yet. or 2) not finding cgrp2 from the skb. - Be-lated thanks to Alexei and Tejun on reviewing v1 and giving advice on this work. v2: - Fix two return cases in cgroup_get_from_fd() - Fix compilation errors when CONFIG_CGROUPS is not used: - arraymap.c: avoid registering BPF_MAP_TYPE_CGROUP_ARRAY - filter.c: tc_cls_act_func_proto() returns NULL on BPF_FUNC_skb_in_cgroup - Add comments to BPF_FUNC_skb_in_cgroup and cgroup_get_from_fd() ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 76fee35da244..54071cf70fb5 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2239,6 +2239,40 @@ bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
}
}
+#ifdef CONFIG_SOCK_CGROUP_DATA
+static u64 bpf_skb_in_cgroup(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
+{
+ struct sk_buff *skb = (struct sk_buff *)(long)r1;
+ struct bpf_map *map = (struct bpf_map *)(long)r2;
+ struct bpf_array *array = container_of(map, struct bpf_array, map);
+ struct cgroup *cgrp;
+ struct sock *sk;
+ u32 i = (u32)r3;
+
+ sk = skb->sk;
+ if (!sk || !sk_fullsock(sk))
+ return -ENOENT;
+
+ if (unlikely(i >= array->map.max_entries))
+ return -E2BIG;
+
+ cgrp = READ_ONCE(array->ptrs[i]);
+ if (unlikely(!cgrp))
+ return -EAGAIN;
+
+ return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
+}
+
+static const struct bpf_func_proto bpf_skb_in_cgroup_proto = {
+ .func = bpf_skb_in_cgroup,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_CONST_MAP_PTR,
+ .arg3_type = ARG_ANYTHING,
+};
+#endif
+
static const struct bpf_func_proto *
sk_filter_func_proto(enum bpf_func_id func_id)
{
@@ -2307,6 +2341,10 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
return bpf_get_event_output_proto();
case BPF_FUNC_get_smp_processor_id:
return &bpf_get_smp_processor_id_proto;
+#ifdef CONFIG_SOCK_CGROUP_DATA
+ case BPF_FUNC_skb_in_cgroup:
+ return &bpf_skb_in_cgroup_proto;
+#endif
default:
return sk_filter_func_proto(func_id);
}