linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH -next 0/4] cgroup: bpf: cgroup2 membership test on skb
@ 2016-06-22  0:23 Martin KaFai Lau
  2016-06-22  0:23 ` [PATCH -next 1/4] cgroup: Add cgroup_get_from_fd Martin KaFai Lau
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Martin KaFai Lau @ 2016-06-22  0:23 UTC (permalink / raw)
  To: cgroups, linux-kernel, netdev
  Cc: Alexei Starovoitov, Daniel Borkmann, Tejun Heo, kernel-team

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.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH -next 1/4] cgroup: Add cgroup_get_from_fd
  2016-06-22  0:23 [PATCH -next 0/4] cgroup: bpf: cgroup2 membership test on skb Martin KaFai Lau
@ 2016-06-22  0:23 ` Martin KaFai Lau
  2016-06-22 15:35   ` Tejun Heo
  2016-06-22  0:23 ` [PATCH -next 2/4] cgroup: bpf: Add BPF_MAP_TYPE_CGROUP_ARRAY Martin KaFai Lau
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Martin KaFai Lau @ 2016-06-22  0:23 UTC (permalink / raw)
  To: cgroups, linux-kernel, netdev
  Cc: Alexei Starovoitov, Daniel Borkmann, Tejun Heo, kernel-team

Add a helper function to get a cgroup2 from a fd.  It will be
stored in a bpf array (BPF_MAP_TYPE_CGROUP_ARRAY) which will
be introduced in the later patch.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Tejun Heo <tj@kernel.org>
---
 include/linux/cgroup.h |  1 +
 kernel/cgroup.c        | 26 ++++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index a20320c..984f73b 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -87,6 +87,7 @@ struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry,
 						       struct cgroup_subsys *ss);
 
 struct cgroup *cgroup_get_from_path(const char *path);
+struct cgroup *cgroup_get_from_fd(int fd);
 
 int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
 int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 86cb5c6..616c751 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -62,6 +62,7 @@
 #include <linux/proc_ns.h>
 #include <linux/nsproxy.h>
 #include <linux/proc_ns.h>
+#include <linux/file.h>
 #include <net/sock.h>
 
 /*
@@ -6205,6 +6206,31 @@ struct cgroup *cgroup_get_from_path(const char *path)
 }
 EXPORT_SYMBOL_GPL(cgroup_get_from_path);
 
+struct cgroup *cgroup_get_from_fd(int fd)
+{
+	struct cgroup_subsys_state *css;
+	struct cgroup *cgrp;
+	struct file *f;
+
+	f = fget_raw(fd);
+	if (!f)
+		return NULL;
+
+	css = css_tryget_online_from_dir(f->f_path.dentry, NULL);
+	fput(f);
+	if (IS_ERR(css))
+		return ERR_CAST(css);
+
+	cgrp = css->cgroup;
+	if (!cgroup_on_dfl(cgrp)) {
+		cgroup_put(cgrp);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return cgrp;
+}
+EXPORT_SYMBOL_GPL(cgroup_get_from_fd);
+
 /*
  * sock->sk_cgrp_data handling.  For more info, see sock_cgroup_data
  * definition in cgroup-defs.h.
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH -next 2/4] cgroup: bpf: Add BPF_MAP_TYPE_CGROUP_ARRAY
  2016-06-22  0:23 [PATCH -next 0/4] cgroup: bpf: cgroup2 membership test on skb Martin KaFai Lau
  2016-06-22  0:23 ` [PATCH -next 1/4] cgroup: Add cgroup_get_from_fd Martin KaFai Lau
@ 2016-06-22  0:23 ` Martin KaFai Lau
  2016-06-22  1:15   ` Alexei Starovoitov
  2016-06-22  2:33   ` kbuild test robot
  2016-06-22  0:23 ` [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto Martin KaFai Lau
  2016-06-22  0:23 ` [PATCH -next 4/4] cgroup: bpf: Add an example to do cgroup checking in BPF Martin KaFai Lau
  3 siblings, 2 replies; 13+ messages in thread
From: Martin KaFai Lau @ 2016-06-22  0:23 UTC (permalink / raw)
  To: cgroups, linux-kernel, netdev
  Cc: Alexei Starovoitov, Daniel Borkmann, Tejun Heo, kernel-team

Add a BPF_MAP_TYPE_CGROUP_ARRAY and its bpf_map_ops's implementations.
To update an element, the caller is expected to obtain a cgroup2 backed
fd by open(cgroup2_dir) and then update the array with that fd.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Tejun Heo <tj@kernel.org>
---
 include/uapi/linux/bpf.h |  1 +
 kernel/bpf/arraymap.c    | 41 +++++++++++++++++++++++++++++++++++++++++
 kernel/bpf/syscall.c     |  3 ++-
 3 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 406459b..ef4e386 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -84,6 +84,7 @@ enum bpf_map_type {
 	BPF_MAP_TYPE_PERCPU_HASH,
 	BPF_MAP_TYPE_PERCPU_ARRAY,
 	BPF_MAP_TYPE_STACK_TRACE,
+	BPF_MAP_TYPE_CGROUP_ARRAY,
 };
 
 enum bpf_prog_type {
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 5af3073..5e279ec 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -539,3 +539,44 @@ static int __init register_perf_event_array_map(void)
 	return 0;
 }
 late_initcall(register_perf_event_array_map);
+
+static void *cgroup_fd_array_get_ptr(struct bpf_map *map,
+				     struct file *map_file /* not used */,
+				     int fd)
+{
+	return cgroup_get_from_fd(fd);
+}
+
+static void cgroup_fd_array_put_ptr(void *ptr)
+{
+	/* cgroup_put free cgrp after a rcu grace period */
+	cgroup_put(ptr);
+}
+
+static void cgroup_fd_array_free(struct bpf_map *map)
+{
+	bpf_fd_array_map_clear(map);
+	fd_array_map_free(map);
+}
+
+static const struct bpf_map_ops cgroup_array_ops = {
+	.map_alloc = fd_array_map_alloc,
+	.map_free = cgroup_fd_array_free,
+	.map_get_next_key = array_map_get_next_key,
+	.map_lookup_elem = fd_array_map_lookup_elem,
+	.map_delete_elem = fd_array_map_delete_elem,
+	.map_fd_get_ptr = cgroup_fd_array_get_ptr,
+	.map_fd_put_ptr = cgroup_fd_array_put_ptr,
+};
+
+static struct bpf_map_type_list cgroup_array_type __read_mostly = {
+	.ops = &cgroup_array_ops,
+	.type = BPF_MAP_TYPE_CGROUP_ARRAY,
+};
+
+static int __init register_cgroup_array_map(void)
+{
+	bpf_register_map_type(&cgroup_array_type);
+	return 0;
+}
+late_initcall(register_cgroup_array_map);
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index c23a4e93..cac13f1 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -393,7 +393,8 @@ static int map_update_elem(union bpf_attr *attr)
 	} else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
 		err = bpf_percpu_array_update(map, key, value, attr->flags);
 	} else if (map->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY ||
-		   map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
+		   map->map_type == BPF_MAP_TYPE_PROG_ARRAY ||
+		   map->map_type == BPF_MAP_TYPE_CGROUP_ARRAY) {
 		rcu_read_lock();
 		err = bpf_fd_array_map_update_elem(map, f.file, key, value,
 						   attr->flags);
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto
  2016-06-22  0:23 [PATCH -next 0/4] cgroup: bpf: cgroup2 membership test on skb Martin KaFai Lau
  2016-06-22  0:23 ` [PATCH -next 1/4] cgroup: Add cgroup_get_from_fd Martin KaFai Lau
  2016-06-22  0:23 ` [PATCH -next 2/4] cgroup: bpf: Add BPF_MAP_TYPE_CGROUP_ARRAY Martin KaFai Lau
@ 2016-06-22  0:23 ` Martin KaFai Lau
  2016-06-22  1:15   ` Alexei Starovoitov
                     ` (2 more replies)
  2016-06-22  0:23 ` [PATCH -next 4/4] cgroup: bpf: Add an example to do cgroup checking in BPF Martin KaFai Lau
  3 siblings, 3 replies; 13+ messages in thread
From: Martin KaFai Lau @ 2016-06-22  0:23 UTC (permalink / raw)
  To: cgroups, linux-kernel, netdev
  Cc: Alexei Starovoitov, Daniel Borkmann, Tejun Heo, kernel-team

Adds a bpf helper, bpf_skb_in_cgroup, to decide if a skb->sk
belongs to a descendant of a cgroup2.  It is similar to the
feature added in netfilter:
commit c38c4597e4bf ("netfilter: implement xt_cgroup cgroup2 path match")

The user is expected to populate a BPF_MAP_TYPE_CGROUP_ARRAY
which will be used by the bpf_skb_in_cgroup.

Modifications to the bpf verifier is to ensure BPF_MAP_TYPE_CGROUP_ARRAY
and bpf_skb_in_cgroup() are always used together.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Tejun Heo <tj@kernel.org>
---
 include/uapi/linux/bpf.h |  1 +
 kernel/bpf/verifier.c    |  8 ++++++++
 net/core/filter.c        | 36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 45 insertions(+)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index ef4e386..a91714bd 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -314,6 +314,7 @@ enum bpf_func_id {
 	 */
 	BPF_FUNC_skb_get_tunnel_opt,
 	BPF_FUNC_skb_set_tunnel_opt,
+	BPF_FUNC_skb_in_cgroup,
 	__BPF_FUNC_MAX_ID,
 };
 
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 668e079..68753e0 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1062,6 +1062,10 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id)
 		if (func_id != BPF_FUNC_get_stackid)
 			goto error;
 		break;
+	case BPF_MAP_TYPE_CGROUP_ARRAY:
+		if (func_id != BPF_FUNC_skb_in_cgroup)
+			goto error;
+		break;
 	default:
 		break;
 	}
@@ -1081,6 +1085,10 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id)
 		if (map->map_type != BPF_MAP_TYPE_STACK_TRACE)
 			goto error;
 		break;
+	case BPF_FUNC_skb_in_cgroup:
+		if (map->map_type != BPF_MAP_TYPE_CGROUP_ARRAY)
+			goto error;
+		break;
 	default:
 		break;
 	}
diff --git a/net/core/filter.c b/net/core/filter.c
index df6860c..410da89 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2024,6 +2024,40 @@ bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
 	}
 }
 
+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);
+	u32 i = (u32)r3;
+	struct cgroup *cgrp;
+	struct sock *sk;
+
+	WARN_ON_ONCE(!rcu_read_lock_held());
+
+	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 -ENOENT;
+
+	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,
+};
+
 static const struct bpf_func_proto *
 sk_filter_func_proto(enum bpf_func_id func_id)
 {
@@ -2086,6 +2120,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
 		return &bpf_get_route_realm_proto;
 	case BPF_FUNC_perf_event_output:
 		return bpf_get_event_output_proto();
+	case BPF_FUNC_skb_in_cgroup:
+		return &bpf_skb_in_cgroup_proto;
 	default:
 		return sk_filter_func_proto(func_id);
 	}
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH -next 4/4] cgroup: bpf: Add an example to do cgroup checking in BPF
  2016-06-22  0:23 [PATCH -next 0/4] cgroup: bpf: cgroup2 membership test on skb Martin KaFai Lau
                   ` (2 preceding siblings ...)
  2016-06-22  0:23 ` [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto Martin KaFai Lau
@ 2016-06-22  0:23 ` Martin KaFai Lau
  2016-06-22  1:19   ` Alexei Starovoitov
  3 siblings, 1 reply; 13+ messages in thread
From: Martin KaFai Lau @ 2016-06-22  0:23 UTC (permalink / raw)
  To: cgroups, linux-kernel, netdev
  Cc: Alexei Starovoitov, Daniel Borkmann, Tejun Heo, kernel-team

test_cgrp2_array_pin.c:
A userland program that creates a bpf_map (BPF_MAP_TYPE_GROUP_ARRAY),
pouplates/updates it with a cgroup2's backed fd and pins it to a
bpf-fs's file.  The pinned file can be loaded by tc and then used
by the bpf prog later.  This program can also update an existing pinned
array and it could be useful for debugging/testing purpose.

test_cgrp2_tc_kern.c:
A bpf prog which should be loaded by tc.  It is to demonstrate
the usage of bpf_skb_in_cgroup.

test_cgrp2_tc.sh:
A script that glues the test_cgrp2_array_pin.c and
test_cgrp2_tc_kern.c together.  The idea is like:
1. Use test_cgrp2_array_pin.c to populate a BPF_MAP_TYPE_CGROUP_ARRAY
   with a cgroup fd
2. Load the test_cgrp2_tc_kern.o by tc
3. Do a 'ping -6 ff02::1%ve' to ensure the packet has been
   dropped because of a match on the cgroup

Most of the lines in test_cgrp2_tc.sh is the boilerplate
to setup the cgroup/bpf-fs/net-devices/netns...etc.  It is
not bulletproof on errors but should work well enough and
give enough debug info if things did not go well.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Tejun Heo <tj@kernel.org>
---
 samples/bpf/Makefile               |   3 +
 samples/bpf/bpf_helpers.h          |   2 +
 samples/bpf/test_cgrp2_array_pin.c | 109 +++++++++++++++++++++
 samples/bpf/test_cgrp2_tc.sh       | 189 +++++++++++++++++++++++++++++++++++++
 samples/bpf/test_cgrp2_tc_kern.c   |  71 ++++++++++++++
 5 files changed, 374 insertions(+)
 create mode 100644 samples/bpf/test_cgrp2_array_pin.c
 create mode 100755 samples/bpf/test_cgrp2_tc.sh
 create mode 100644 samples/bpf/test_cgrp2_tc_kern.c

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 0bf2478..a98b780 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -20,6 +20,7 @@ hostprogs-y += offwaketime
 hostprogs-y += spintest
 hostprogs-y += map_perf_test
 hostprogs-y += test_overhead
+hostprogs-y += test_cgrp2_array_pin
 
 test_verifier-objs := test_verifier.o libbpf.o
 test_maps-objs := test_maps.o libbpf.o
@@ -40,6 +41,7 @@ offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o
 spintest-objs := bpf_load.o libbpf.o spintest_user.o
 map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o
 test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o
+test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
@@ -61,6 +63,7 @@ always += map_perf_test_kern.o
 always += test_overhead_tp_kern.o
 always += test_overhead_kprobe_kern.o
 always += parse_varlen.o parse_simple.o parse_ldabs.o
+always += test_cgrp2_tc_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
 
diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h
index 7904a2a..84e3fd9 100644
--- a/samples/bpf/bpf_helpers.h
+++ b/samples/bpf/bpf_helpers.h
@@ -70,6 +70,8 @@ static int (*bpf_l3_csum_replace)(void *ctx, int off, int from, int to, int flag
 	(void *) BPF_FUNC_l3_csum_replace;
 static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flags) =
 	(void *) BPF_FUNC_l4_csum_replace;
+static int (*bpf_skb_in_cgroup)(void *ctx, void *map, int index) =
+	(void *) BPF_FUNC_skb_in_cgroup;
 
 #if defined(__x86_64__)
 
diff --git a/samples/bpf/test_cgrp2_array_pin.c b/samples/bpf/test_cgrp2_array_pin.c
new file mode 100644
index 0000000..70e86f7
--- /dev/null
+++ b/samples/bpf/test_cgrp2_array_pin.c
@@ -0,0 +1,109 @@
+/* Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include <linux/unistd.h>
+#include <linux/bpf.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "libbpf.h"
+
+static void usage(void)
+{
+	printf("Usage: test_cgrp2_array_pin [...]\n");
+	printf("       -F <file>   File to pin an BPF cgroup array\n");
+	printf("       -U <file>   Update an already pinned BPF cgroup array\n");
+	printf("       -v <value>  Full path of the cgroup2\n");
+	printf("       -h          Display this help\n");
+}
+
+int main(int argc, char **argv)
+{
+	const char *pinned_file = NULL, *cg2 = NULL;
+	int create_array = 1;
+	int array_key = 0;
+	int array_fd = -1;
+	int cg2_fd = -1;
+	int ret = -1;
+	int opt;
+
+	while ((opt = getopt(argc, argv, "F:U:v:")) != -1) {
+		switch (opt) {
+		/* General args */
+		case 'F':
+			pinned_file = optarg;
+			break;
+		case 'U':
+			pinned_file = optarg;
+			create_array = 0;
+			break;
+		case 'v':
+			cg2 = optarg;
+			break;
+		default:
+			usage();
+			goto out;
+		}
+	}
+
+	if (!cg2 || !pinned_file) {
+		usage();
+		goto out;
+	}
+
+	cg2_fd = open(cg2, O_RDONLY);
+	if (cg2_fd < 0) {
+		fprintf(stderr, "open(%s,...): %s(%d)\n",
+			cg2, strerror(errno), errno);
+		goto out;
+	}
+
+	if (create_array) {
+		array_fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_ARRAY,
+					  sizeof(uint32_t), sizeof(uint32_t),
+					  1, 0);
+		if (array_fd < 0) {
+			fprintf(stderr,
+				"bpf_create_map(BPF_MAP_TYPE_CGROUP_ARRAY,...): %s(%d)\n",
+				strerror(errno), errno);
+			goto out;
+		}
+	} else {
+		array_fd = bpf_obj_get(pinned_file);
+		if (array_fd < 0) {
+			fprintf(stderr, "bpf_obj_get(%s): %s(%d)\n",
+				pinned_file, strerror(errno), errno);
+			goto out;
+		}
+	}
+
+	ret = bpf_update_elem(array_fd, &array_key, &cg2_fd, 0);
+	if (ret) {
+		perror("bpf_update_elem");
+		goto out;
+	}
+
+	if (create_array) {
+		ret = bpf_obj_pin(array_fd, pinned_file);
+		if (ret) {
+			fprintf(stderr, "bpf_obj_pin(..., %s): %s(%d)\n",
+				pinned_file, strerror(errno), errno);
+			goto out;
+		}
+	}
+
+out:
+	if (array_fd != -1)
+		close(array_fd);
+	if (cg2_fd != -1)
+		close(cg2_fd);
+	return ret;
+}
diff --git a/samples/bpf/test_cgrp2_tc.sh b/samples/bpf/test_cgrp2_tc.sh
new file mode 100755
index 0000000..d2aa98f
--- /dev/null
+++ b/samples/bpf/test_cgrp2_tc.sh
@@ -0,0 +1,189 @@
+#!/bin/bash
+
+MY_DIR=$(dirname $0)
+# Details on the bpf prog
+BPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin'
+BPF_PROG="$MY_DIR/test_cgrp2_tc_kern.o"
+BPF_SECTION='filter'
+
+[ -z "$TC" ] && TC='tc'
+[ -z "$IP" ] && IP='ip'
+
+# Names of the veth interface, net namespace...etc.
+HOST_IFC='ve'
+NS_IFC='vens'
+NS='ns'
+
+find_mnt() {
+    cat /proc/mounts | \
+	awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }'
+}
+
+# Init cgroup2 vars
+init_cgrp2_vars() {
+    CGRP2_ROOT=$(find_mnt cgroup2)
+    if [ -z "$CGRP2_ROOT" ]
+    then
+	CGRP2_ROOT='/mnt/cgroup2'
+	MOUNT_CGRP2="yes"
+    fi
+    CGRP2_TC="$CGRP2_ROOT/tc"
+    CGRP2_TC_LEAF="$CGRP2_TC/leaf"
+}
+
+# Init bpf fs vars
+init_bpf_fs_vars() {
+    BPF_FS_ROOT=$(find_mnt bpf)
+    if [ -z "$BPF_FS_ROOT" ]
+    then
+	BPF_FS_ROOT='/sys/fs/bpf'
+	MOUNT_BPF_FS="yes"
+    fi
+    BPF_FS_TC="$BPF_FS_ROOT/tc"
+    BPF_FS_TC_SHARE="$BPF_FS_TC/globals"
+}
+
+setup_cgrp2() {
+    case $1 in
+	start)
+	    if [ "$MOUNT_CGRP2" == 'yes' ]
+	    then
+		[ -d $CGRP2_ROOT ] || mkdir -p $CGRP2_ROOT
+		mount -t cgroup2 none $CGRP2_ROOT || return $?
+	    fi
+	    mkdir -p $CGRP2_TC_LEAF
+	    ;;
+	*)
+	    rmdir $CGRP2_TC_LEAF && rmdir $CGRP2_TC
+	    [ "$MOUNT_CGRP2" == 'yes' ] && umount $CGRP2_ROOT
+	    ;;
+    esac
+}
+
+setup_bpf_fs() {
+    case $1 in
+	start)
+	    [ "$MOUNT_BPF_FS" != 'yes' ] || mount -t bpf none $BPF_FS_ROOT || \
+		return $?
+	    mkdir -p $BPF_FS_TC_SHARE || return $?
+	    $MY_DIR/test_cgrp2_array_pin -F "$BPF_FS_TC_SHARE/$BPF_CGRP2_ARRAY_NAME" -v $CGRP2_TC
+	    ;;
+	*)
+	    rm $BPF_FS_TC_SHARE/$BPF_CGRP2_ARRAY_NAME
+	    rmdir $BPF_FS_TC_SHARE >& /dev/null && rmdir $BPF_FS_TC >& /dev/null
+	    [ "$MOUNT_BPF_FS" == 'yes' ] && umount $BPF_FS_ROOT
+	    ;;
+    esac
+}
+
+setup_net() {
+    case $1 in
+	start)
+	    $IP link add $HOST_IFC type veth peer name $NS_IFC || return $?
+	    $IP link set dev $HOST_IFC up || return $?
+	    sysctl -q net.ipv6.conf.$HOST_IFC.accept_dad=0
+
+	    $IP netns add ns || return $?
+	    $IP link set dev $NS_IFC netns ns || return $?
+	    $IP -n $NS link set dev $NS_IFC up || return $?
+	    $IP netns exec $NS sysctl -q net.ipv6.conf.$NS_IFC.accept_dad=0
+	    $TC qdisc add dev $HOST_IFC clsact || return $?
+	    $TC filter add dev $HOST_IFC egress bpf da obj $BPF_PROG sec $BPF_SECTION || return $?
+	    ;;
+	*)
+	    $IP netns del $NS
+	    $IP link del $HOST_IFC
+	    ;;
+    esac
+}
+
+run_in_cgrp() {
+    # Fork another bash and move it under the specified cgroup.
+    # It makes the cgroup cleanup easier at the end of the test.
+    cmd='echo $$ > '
+    cmd="$cmd $1/cgroup.procs; exec $2"
+    bash -c "$cmd"
+}
+
+do_test() {
+    run_in_cgrp $CGRP2_TC_LEAF "ping -6 -c3 ff02::1%$HOST_IFC >& /dev/null"
+    local dropped=$($TC -s qdisc show dev $HOST_IFC | tail -3 | \
+			   awk '/drop/{print substr($7, 0, index($7, ",")-1)}')
+    if [[ $dropped -eq 0 ]]
+    then
+	echo "FAIL"
+	return 1
+    else
+	echo "Successfully filtered $dropped packets"
+	return 0
+    fi
+}
+
+do_exit() {
+    if [ "$DEBUG" == "yes" ]
+    then
+	echo "------ DEBUG ------"
+	echo "mount: "; mount | egrep '(cgroup2|bpf)'; echo
+	echo "$CGRP2_TC_LEAF: "; ls -l $CGRP2_TC_LEAF; echo
+	echo "$BPF_FS_TC_SHARE: "; ls -l $BPF_FS_TC_SHARE; echo
+	echo "Host net:"
+	$IP netns
+	$IP link show dev $HOST_IFC
+	$IP -6 a show dev $HOST_IFC
+	$TC -s qdisc show dev $HOST_IFC
+	echo
+	echo "$NS net:"
+	$IP -n $NS link show dev $NS_IFC
+	$IP -n $NS -6 link show dev $NS_IFC
+	echo "------ DEBUG ------"
+	echo
+    fi
+
+    if [ "$MODE" != 'nocleanup' ]
+    then
+	setup_net stop
+	setup_bpf_fs stop
+	setup_cgrp2 stop
+    fi
+}
+
+init_cgrp2_vars
+init_bpf_fs_vars
+
+while [[ $# -ge 1 ]]
+do
+    a="$1"
+    case $a in
+	debug)
+	    DEBUG='yes'
+	    shift 1
+	    ;;
+	cleanup-only)
+	    MODE='cleanuponly'
+	    shift 1
+	    ;;
+	no-cleanup)
+	    MODE='nocleanup'
+	    shift 1
+	    ;;
+	*)
+	    echo "test_cgrp2_tc [debug] [cleanup-only | no-cleanup]"
+	    echo "  debug: Print cgrp and network setup details at the end of the test"
+	    echo "  cleanup-only: Try to cleanup things from last test.  No test will be run"
+	    echo "  no-cleanup: Run the test but don't do cleanup at the end"
+	    echo "[Note: If no arg is given, it will run the test and do cleanup at the end]"
+	    echo
+	    exit -1
+	    ;;
+    esac
+done
+
+trap do_exit 0
+
+[ "$MODE" == 'cleanuponly' ] && exit
+
+setup_cgrp2 start || exit $?
+setup_bpf_fs start || exit $?
+setup_net start || exit $?
+do_test
+echo
diff --git a/samples/bpf/test_cgrp2_tc_kern.c b/samples/bpf/test_cgrp2_tc_kern.c
new file mode 100644
index 0000000..789c5a6
--- /dev/null
+++ b/samples/bpf/test_cgrp2_tc_kern.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include <uapi/linux/if_ether.h>
+#include <uapi/linux/in6.h>
+#include <uapi/linux/ipv6.h>
+#include <uapi/linux/pkt_cls.h>
+#include <uapi/linux/bpf.h>
+#include "bpf_helpers.h"
+
+#define DEFAULT_PKTGEN_UDP_PORT 9
+
+/* copy of 'struct ethhdr' without __packed */
+struct eth_hdr {
+	unsigned char   h_dest[ETH_ALEN];
+	unsigned char   h_source[ETH_ALEN];
+	unsigned short  h_proto;
+};
+
+#define PIN_GLOBAL_NS		2
+struct bpf_elf_map {
+	__u32 type;
+	__u32 size_key;
+	__u32 size_value;
+	__u32 max_elem;
+	__u32 flags;
+	__u32 id;
+	__u32 pinning;
+};
+
+struct bpf_elf_map SEC("maps") test_cgrp2_array_pin = {
+	.type		= BPF_MAP_TYPE_CGROUP_ARRAY,
+	.size_key	= sizeof(uint32_t),
+	.size_value	= sizeof(uint32_t),
+	.pinning	= PIN_GLOBAL_NS,
+	.max_elem	= 1,
+};
+
+SEC("filter")
+int handle_egress(struct __sk_buff *skb)
+{
+	void *data = (void *)(long)skb->data;
+	struct eth_hdr *eth = data;
+	struct ipv6hdr *ip6h = data + sizeof(*eth);
+	void *data_end = (void *)(long)skb->data_end;
+	char dont_care_msg[] = "dont care %04x %d\n";
+	char pass_msg[] = "pass\n";
+	char reject_msg[] = "reject\n";
+
+	/* single length check */
+	if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
+		return TC_ACT_OK;
+
+	if (eth->h_proto != htons(ETH_P_IPV6) ||
+	    ip6h->nexthdr != IPPROTO_ICMPV6) {
+		bpf_trace_printk(dont_care_msg, sizeof(dont_care_msg),
+				 eth->h_proto, ip6h->nexthdr);
+		return TC_ACT_OK;
+	} else if (bpf_skb_in_cgroup(skb, &test_cgrp2_array_pin, 0) != 1) {
+		bpf_trace_printk(pass_msg, sizeof(pass_msg));
+		return TC_ACT_OK;
+	} else {
+		bpf_trace_printk(reject_msg, sizeof(reject_msg));
+		return TC_ACT_SHOT;
+	}
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto
  2016-06-22  0:23 ` [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto Martin KaFai Lau
@ 2016-06-22  1:15   ` Alexei Starovoitov
  2016-06-22  6:19     ` Martin KaFai Lau
  2016-06-22  1:25   ` kbuild test robot
  2016-06-22  2:15   ` kbuild test robot
  2 siblings, 1 reply; 13+ messages in thread
From: Alexei Starovoitov @ 2016-06-22  1:15 UTC (permalink / raw)
  To: Martin KaFai Lau
  Cc: cgroups, linux-kernel, netdev, Alexei Starovoitov,
	Daniel Borkmann, Tejun Heo, kernel-team

On Tue, Jun 21, 2016 at 05:23:21PM -0700, Martin KaFai Lau wrote:
> Adds a bpf helper, bpf_skb_in_cgroup, to decide if a skb->sk
> belongs to a descendant of a cgroup2.  It is similar to the
> feature added in netfilter:
> commit c38c4597e4bf ("netfilter: implement xt_cgroup cgroup2 path match")
> 
> The user is expected to populate a BPF_MAP_TYPE_CGROUP_ARRAY
> which will be used by the bpf_skb_in_cgroup.
> 
> Modifications to the bpf verifier is to ensure BPF_MAP_TYPE_CGROUP_ARRAY
> and bpf_skb_in_cgroup() are always used together.
> 
> Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Tejun Heo <tj@kernel.org>
> ---
>  include/uapi/linux/bpf.h |  1 +
>  kernel/bpf/verifier.c    |  8 ++++++++
>  net/core/filter.c        | 36 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 45 insertions(+)
> 
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index ef4e386..a91714bd 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -314,6 +314,7 @@ enum bpf_func_id {
>  	 */
>  	BPF_FUNC_skb_get_tunnel_opt,
>  	BPF_FUNC_skb_set_tunnel_opt,
> +	BPF_FUNC_skb_in_cgroup,
...
> +static u64 bpf_skb_in_cgroup(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
> +{
...
> +	if (unlikely(!cgrp))
> +		return -ENOENT;
> +
> +	return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);

if you'd need to respin the patch for other reasons please add kdoc
to bpf.h for this new helper similar to other helpers.
To say that 0 or 1 return values is indication of cg2 descendant relation
and < 0 in case of error.

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH -next 2/4] cgroup: bpf: Add BPF_MAP_TYPE_CGROUP_ARRAY
  2016-06-22  0:23 ` [PATCH -next 2/4] cgroup: bpf: Add BPF_MAP_TYPE_CGROUP_ARRAY Martin KaFai Lau
@ 2016-06-22  1:15   ` Alexei Starovoitov
  2016-06-22  2:33   ` kbuild test robot
  1 sibling, 0 replies; 13+ messages in thread
From: Alexei Starovoitov @ 2016-06-22  1:15 UTC (permalink / raw)
  To: Martin KaFai Lau
  Cc: cgroups, linux-kernel, netdev, Alexei Starovoitov,
	Daniel Borkmann, Tejun Heo, kernel-team

On Tue, Jun 21, 2016 at 05:23:20PM -0700, Martin KaFai Lau wrote:
> Add a BPF_MAP_TYPE_CGROUP_ARRAY and its bpf_map_ops's implementations.
> To update an element, the caller is expected to obtain a cgroup2 backed
> fd by open(cgroup2_dir) and then update the array with that fd.
> 
> Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Tejun Heo <tj@kernel.org>

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH -next 4/4] cgroup: bpf: Add an example to do cgroup checking in BPF
  2016-06-22  0:23 ` [PATCH -next 4/4] cgroup: bpf: Add an example to do cgroup checking in BPF Martin KaFai Lau
@ 2016-06-22  1:19   ` Alexei Starovoitov
  0 siblings, 0 replies; 13+ messages in thread
From: Alexei Starovoitov @ 2016-06-22  1:19 UTC (permalink / raw)
  To: Martin KaFai Lau
  Cc: cgroups, linux-kernel, netdev, Alexei Starovoitov,
	Daniel Borkmann, Tejun Heo, kernel-team

On Tue, Jun 21, 2016 at 05:23:22PM -0700, Martin KaFai Lau wrote:
> test_cgrp2_array_pin.c:
> A userland program that creates a bpf_map (BPF_MAP_TYPE_GROUP_ARRAY),
> pouplates/updates it with a cgroup2's backed fd and pins it to a
> bpf-fs's file.  The pinned file can be loaded by tc and then used
> by the bpf prog later.  This program can also update an existing pinned
> array and it could be useful for debugging/testing purpose.
> 
> test_cgrp2_tc_kern.c:
> A bpf prog which should be loaded by tc.  It is to demonstrate
> the usage of bpf_skb_in_cgroup.
> 
> test_cgrp2_tc.sh:
> A script that glues the test_cgrp2_array_pin.c and
> test_cgrp2_tc_kern.c together.  The idea is like:
> 1. Use test_cgrp2_array_pin.c to populate a BPF_MAP_TYPE_CGROUP_ARRAY
>    with a cgroup fd
> 2. Load the test_cgrp2_tc_kern.o by tc
> 3. Do a 'ping -6 ff02::1%ve' to ensure the packet has been
>    dropped because of a match on the cgroup
> 
> Most of the lines in test_cgrp2_tc.sh is the boilerplate
> to setup the cgroup/bpf-fs/net-devices/netns...etc.  It is
> not bulletproof on errors but should work well enough and
> give enough debug info if things did not go well.
> 
> Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Tejun Heo <tj@kernel.org>
> ---
>  samples/bpf/Makefile               |   3 +
>  samples/bpf/bpf_helpers.h          |   2 +
>  samples/bpf/test_cgrp2_array_pin.c | 109 +++++++++++++++++++++
>  samples/bpf/test_cgrp2_tc.sh       | 189 +++++++++++++++++++++++++++++++++++++
>  samples/bpf/test_cgrp2_tc_kern.c   |  71 ++++++++++++++
>  5 files changed, 374 insertions(+)
...
> +struct bpf_elf_map SEC("maps") test_cgrp2_array_pin = {
> +	.type		= BPF_MAP_TYPE_CGROUP_ARRAY,
> +	.size_key	= sizeof(uint32_t),
> +	.size_value	= sizeof(uint32_t),
> +	.pinning	= PIN_GLOBAL_NS,
> +	.max_elem	= 1,
> +};
> +
> +SEC("filter")
> +int handle_egress(struct __sk_buff *skb)
> +{
> +	void *data = (void *)(long)skb->data;
> +	struct eth_hdr *eth = data;
> +	struct ipv6hdr *ip6h = data + sizeof(*eth);
> +	void *data_end = (void *)(long)skb->data_end;
> +	char dont_care_msg[] = "dont care %04x %d\n";
> +	char pass_msg[] = "pass\n";
> +	char reject_msg[] = "reject\n";
> +
> +	/* single length check */
> +	if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
> +		return TC_ACT_OK;

love the test case.
It's using tc + clsact + cls_bpf in da mode + bpffs + direct packet access
and new cgroup helper.
All the most recent features I can think of :)

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto
  2016-06-22  0:23 ` [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto Martin KaFai Lau
  2016-06-22  1:15   ` Alexei Starovoitov
@ 2016-06-22  1:25   ` kbuild test robot
  2016-06-22  2:15   ` kbuild test robot
  2 siblings, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2016-06-22  1:25 UTC (permalink / raw)
  To: Martin KaFai Lau
  Cc: kbuild-all, cgroups, linux-kernel, netdev, Alexei Starovoitov,
	Daniel Borkmann, Tejun Heo, kernel-team

[-- Attachment #1: Type: text/plain, Size: 1792 bytes --]

Hi,

[auto build test ERROR on next-20160621]

url:    https://github.com/0day-ci/linux/commits/Martin-KaFai-Lau/cgroup-bpf-cgroup2-membership-test-on-skb/20160622-082800
config: i386-randconfig-s1-201625 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   net/core/filter.c: In function 'bpf_skb_in_cgroup':
>> net/core/filter.c:2049:30: error: implicit declaration of function 'sock_cgroup_ptr' [-Werror=implicit-function-declaration]
     return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
                                 ^~~~~~~~~~~~~~~
>> net/core/filter.c:2049:30: warning: passing argument 1 of 'cgroup_is_descendant' makes pointer from integer without a cast [-Wint-conversion]
   In file included from include/net/netprio_cgroup.h:17:0,
                    from include/linux/netdevice.h:48,
                    from net/core/filter.c:31:
   include/linux/cgroup.h:492:20: note: expected 'struct cgroup *' but argument is of type 'int'
    static inline bool cgroup_is_descendant(struct cgroup *cgrp,
                       ^~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/sock_cgroup_ptr +2049 net/core/filter.c

  2043			return -E2BIG;
  2044	
  2045		cgrp = READ_ONCE(array->ptrs[i]);
  2046		if (unlikely(!cgrp))
  2047			return -ENOENT;
  2048	
> 2049		return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
  2050	}
  2051	
  2052	static const struct bpf_func_proto bpf_skb_in_cgroup_proto = {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 27072 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto
  2016-06-22  0:23 ` [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto Martin KaFai Lau
  2016-06-22  1:15   ` Alexei Starovoitov
  2016-06-22  1:25   ` kbuild test robot
@ 2016-06-22  2:15   ` kbuild test robot
  2 siblings, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2016-06-22  2:15 UTC (permalink / raw)
  To: Martin KaFai Lau
  Cc: kbuild-all, cgroups, linux-kernel, netdev, Alexei Starovoitov,
	Daniel Borkmann, Tejun Heo, kernel-team

[-- Attachment #1: Type: text/plain, Size: 1645 bytes --]

Hi,

[auto build test ERROR on next-20160621]

url:    https://github.com/0day-ci/linux/commits/Martin-KaFai-Lau/cgroup-bpf-cgroup2-membership-test-on-skb/20160622-082800
config: sh-titan_defconfig (attached as .config)
compiler: sh4-linux-gnu-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sh 

All errors (new ones prefixed by >>):

   net/core/filter.c: In function 'bpf_skb_in_cgroup':
>> net/core/filter.c:2049:9: error: implicit declaration of function 'cgroup_is_descendant' [-Werror=implicit-function-declaration]
     return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
            ^
   net/core/filter.c:2049:30: error: implicit declaration of function 'sock_cgroup_ptr' [-Werror=implicit-function-declaration]
     return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
                                 ^
   cc1: some warnings being treated as errors

vim +/cgroup_is_descendant +2049 net/core/filter.c

  2043			return -E2BIG;
  2044	
  2045		cgrp = READ_ONCE(array->ptrs[i]);
  2046		if (unlikely(!cgrp))
  2047			return -ENOENT;
  2048	
> 2049		return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
  2050	}
  2051	
  2052	static const struct bpf_func_proto bpf_skb_in_cgroup_proto = {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 16201 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH -next 2/4] cgroup: bpf: Add BPF_MAP_TYPE_CGROUP_ARRAY
  2016-06-22  0:23 ` [PATCH -next 2/4] cgroup: bpf: Add BPF_MAP_TYPE_CGROUP_ARRAY Martin KaFai Lau
  2016-06-22  1:15   ` Alexei Starovoitov
@ 2016-06-22  2:33   ` kbuild test robot
  1 sibling, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2016-06-22  2:33 UTC (permalink / raw)
  To: Martin KaFai Lau
  Cc: kbuild-all, cgroups, linux-kernel, netdev, Alexei Starovoitov,
	Daniel Borkmann, Tejun Heo, kernel-team

[-- Attachment #1: Type: text/plain, Size: 1861 bytes --]

Hi,

[auto build test ERROR on next-20160621]

url:    https://github.com/0day-ci/linux/commits/Martin-KaFai-Lau/cgroup-bpf-cgroup2-membership-test-on-skb/20160622-082800
config: m68k-sun3_defconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 4.9.0
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=m68k 

All error/warnings (new ones prefixed by >>):

   kernel/bpf/arraymap.c: In function 'cgroup_fd_array_get_ptr':
>> kernel/bpf/arraymap.c:547:2: error: implicit declaration of function 'cgroup_get_from_fd' [-Werror=implicit-function-declaration]
     return cgroup_get_from_fd(fd);
     ^
>> kernel/bpf/arraymap.c:547:2: warning: return makes pointer from integer without a cast
   kernel/bpf/arraymap.c: In function 'cgroup_fd_array_put_ptr':
>> kernel/bpf/arraymap.c:553:2: error: implicit declaration of function 'cgroup_put' [-Werror=implicit-function-declaration]
     cgroup_put(ptr);
     ^
   cc1: some warnings being treated as errors

vim +/cgroup_get_from_fd +547 kernel/bpf/arraymap.c

   541	late_initcall(register_perf_event_array_map);
   542	
   543	static void *cgroup_fd_array_get_ptr(struct bpf_map *map,
   544					     struct file *map_file /* not used */,
   545					     int fd)
   546	{
 > 547		return cgroup_get_from_fd(fd);
   548	}
   549	
   550	static void cgroup_fd_array_put_ptr(void *ptr)
   551	{
   552		/* cgroup_put free cgrp after a rcu grace period */
 > 553		cgroup_put(ptr);
   554	}
   555	
   556	static void cgroup_fd_array_free(struct bpf_map *map)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 11770 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto
  2016-06-22  1:15   ` Alexei Starovoitov
@ 2016-06-22  6:19     ` Martin KaFai Lau
  0 siblings, 0 replies; 13+ messages in thread
From: Martin KaFai Lau @ 2016-06-22  6:19 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: cgroups, linux-kernel, netdev, Alexei Starovoitov,
	Daniel Borkmann, Tejun Heo, kernel-team

On Tue, Jun 21, 2016 at 06:15:13PM -0700, Alexei Starovoitov wrote:
> On Tue, Jun 21, 2016 at 05:23:21PM -0700, Martin KaFai Lau wrote:
> > Adds a bpf helper, bpf_skb_in_cgroup, to decide if a skb->sk
> > belongs to a descendant of a cgroup2.  It is similar to the
> > feature added in netfilter:
> > commit c38c4597e4bf ("netfilter: implement xt_cgroup cgroup2 path match")
> >
> > The user is expected to populate a BPF_MAP_TYPE_CGROUP_ARRAY
> > which will be used by the bpf_skb_in_cgroup.
> >
> > Modifications to the bpf verifier is to ensure BPF_MAP_TYPE_CGROUP_ARRAY
> > and bpf_skb_in_cgroup() are always used together.
> >
> > Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> > Cc: Alexei Starovoitov <ast@fb.com>
> > Cc: Daniel Borkmann <daniel@iogearbox.net>
> > Cc: Tejun Heo <tj@kernel.org>
> > ---
> >  include/uapi/linux/bpf.h |  1 +
> >  kernel/bpf/verifier.c    |  8 ++++++++
> >  net/core/filter.c        | 36 ++++++++++++++++++++++++++++++++++++
> >  3 files changed, 45 insertions(+)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index ef4e386..a91714bd 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -314,6 +314,7 @@ enum bpf_func_id {
> >  	 */
> >  	BPF_FUNC_skb_get_tunnel_opt,
> >  	BPF_FUNC_skb_set_tunnel_opt,
> > +	BPF_FUNC_skb_in_cgroup,
> ...
> > +static u64 bpf_skb_in_cgroup(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
> > +{
> ...
> > +	if (unlikely(!cgrp))
> > +		return -ENOENT;
> > +
> > +	return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
>
> if you'd need to respin the patch for other reasons please add kdoc
> to bpf.h for this new helper similar to other helpers.
> To say that 0 or 1 return values is indication of cg2 descendant relation
> and < 0 in case of error.
Will do.

I will also address the '#ifndef CONFIG_CGROUPS' case in v2, as reported
by the kbuild test.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH -next 1/4] cgroup: Add cgroup_get_from_fd
  2016-06-22  0:23 ` [PATCH -next 1/4] cgroup: Add cgroup_get_from_fd Martin KaFai Lau
@ 2016-06-22 15:35   ` Tejun Heo
  0 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2016-06-22 15:35 UTC (permalink / raw)
  To: Martin KaFai Lau
  Cc: cgroups, linux-kernel, netdev, Alexei Starovoitov,
	Daniel Borkmann, kernel-team

Hello, Martin.

On Tue, Jun 21, 2016 at 05:23:19PM -0700, Martin KaFai Lau wrote:
> @@ -6205,6 +6206,31 @@ struct cgroup *cgroup_get_from_path(const char *path)
>  }
>  EXPORT_SYMBOL_GPL(cgroup_get_from_path);

Proper function comment would be nice.

> +struct cgroup *cgroup_get_from_fd(int fd)
> +{
> +	struct cgroup_subsys_state *css;
> +	struct cgroup *cgrp;
> +	struct file *f;
> +
> +	f = fget_raw(fd);
> +	if (!f)
> +		return NULL;

It returns NULL here.

> +	css = css_tryget_online_from_dir(f->f_path.dentry, NULL);
> +	fput(f);
> +	if (IS_ERR(css))
> +		return ERR_CAST(css);
> +
> +	cgrp = css->cgroup;
> +	if (!cgroup_on_dfl(cgrp)) {
> +		cgroup_put(cgrp);
> +		return ERR_PTR(-EINVAL);

But an ERR_PTR value here.  Is this intentional?  Also, wouldn't it
make more sense to return -EBADF here, given that that's what
css_tryget_online_from_dir() would return if the filesystem type is
wrong?

Thanks!

-- 
tejun

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2016-06-22 15:35 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-22  0:23 [PATCH -next 0/4] cgroup: bpf: cgroup2 membership test on skb Martin KaFai Lau
2016-06-22  0:23 ` [PATCH -next 1/4] cgroup: Add cgroup_get_from_fd Martin KaFai Lau
2016-06-22 15:35   ` Tejun Heo
2016-06-22  0:23 ` [PATCH -next 2/4] cgroup: bpf: Add BPF_MAP_TYPE_CGROUP_ARRAY Martin KaFai Lau
2016-06-22  1:15   ` Alexei Starovoitov
2016-06-22  2:33   ` kbuild test robot
2016-06-22  0:23 ` [PATCH -next 3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto Martin KaFai Lau
2016-06-22  1:15   ` Alexei Starovoitov
2016-06-22  6:19     ` Martin KaFai Lau
2016-06-22  1:25   ` kbuild test robot
2016-06-22  2:15   ` kbuild test robot
2016-06-22  0:23 ` [PATCH -next 4/4] cgroup: bpf: Add an example to do cgroup checking in BPF Martin KaFai Lau
2016-06-22  1:19   ` Alexei Starovoitov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).