All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 net-next 0/5] eBPF-based device cgroup controller
@ 2017-11-02 14:54 Roman Gushchin
  2017-11-02 14:54 ` [PATCH v2 net-next 1/5] device_cgroup: add DEVCG_ prefix to ACC_* and DEV_* constants Roman Gushchin
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Roman Gushchin @ 2017-11-02 14:54 UTC (permalink / raw)
  To: netdev
  Cc: Tejun Heo, Alexei Starovoitov, Daniel Borkmann, linux-kernel,
	kernel-team, Roman Gushchin

This patchset introduces an eBPF-based device controller for cgroup v2.

Patches (1) and (2) are a preparational work required to share some code
  with the existing device controller implementation.
Patch (3) is the main patch, which introduces a new bpf prog type
  and all necessary infrastructure.
Patch (4) moves cgroup_helpers.c/h to use them by patch (4).
Patch (5) implements an example of eBPF program which controls access
  to device files and corresponding userspace test.

v2:
  Added patch (1).

v1:
  https://lkml.org/lkml/2017/11/1/363

Roman Gushchin (5):
  device_cgroup: add DEVCG_ prefix to ACC_* and DEV_* constants
  device_cgroup: prepare code for bpf-based device controller
  bpf, cgroup: implement eBPF-based device controller for cgroup v2
  bpf: move cgroup_helpers from samples/bpf/ to
    tools/testing/selftesting/bpf/
  selftests/bpf: add a test for device cgroup controller

 include/linux/bpf-cgroup.h                         | 15 ++++
 include/linux/bpf_types.h                          |  3 +
 include/linux/device_cgroup.h                      | 67 +++++++++++++++-
 include/uapi/linux/bpf.h                           | 15 ++++
 kernel/bpf/cgroup.c                                | 67 ++++++++++++++++
 kernel/bpf/syscall.c                               |  7 ++
 kernel/bpf/verifier.c                              |  1 +
 samples/bpf/Makefile                               |  5 +-
 security/device_cgroup.c                           | 91 ++++++---------------
 tools/include/uapi/linux/bpf.h                     | 15 ++++
 tools/testing/selftests/bpf/Makefile               |  6 +-
 .../testing/selftests}/bpf/cgroup_helpers.c        |  0
 .../testing/selftests}/bpf/cgroup_helpers.h        |  0
 tools/testing/selftests/bpf/dev_cgroup.c           | 60 ++++++++++++++
 tools/testing/selftests/bpf/test_dev_cgroup.c      | 93 ++++++++++++++++++++++
 15 files changed, 369 insertions(+), 76 deletions(-)
 rename {samples => tools/testing/selftests}/bpf/cgroup_helpers.c (100%)
 rename {samples => tools/testing/selftests}/bpf/cgroup_helpers.h (100%)
 create mode 100644 tools/testing/selftests/bpf/dev_cgroup.c
 create mode 100644 tools/testing/selftests/bpf/test_dev_cgroup.c

-- 
2.13.6

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

* [PATCH v2 net-next 1/5] device_cgroup: add DEVCG_ prefix to ACC_* and DEV_* constants
  2017-11-02 14:54 [PATCH v2 net-next 0/5] eBPF-based device cgroup controller Roman Gushchin
@ 2017-11-02 14:54 ` Roman Gushchin
  2017-11-02 14:54 ` [PATCH v2 net-next 2/5] device_cgroup: prepare code for bpf-based device controller Roman Gushchin
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Roman Gushchin @ 2017-11-02 14:54 UTC (permalink / raw)
  To: netdev
  Cc: Tejun Heo, Alexei Starovoitov, Daniel Borkmann, linux-kernel,
	kernel-team, Roman Gushchin, David S . Miller

Rename device type and access type constants defined in
security/device_cgroup.c by adding the DEVCG_ prefix.

The reason behind this renaming is to make them global namespace
friendly, as they will be moved to the corresponding header file
by following patches.

Signed-off-by: Roman Gushchin <guro@fb.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Tejun Heo <tj@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
 security/device_cgroup.c | 72 ++++++++++++++++++++++++------------------------
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 03c1652c9a1f..76cc0cbbb10d 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -14,14 +14,14 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 
-#define ACC_MKNOD 1
-#define ACC_READ  2
-#define ACC_WRITE 4
-#define ACC_MASK (ACC_MKNOD | ACC_READ | ACC_WRITE)
+#define DEVCG_ACC_MKNOD 1
+#define DEVCG_ACC_READ  2
+#define DEVCG_ACC_WRITE 4
+#define DEVCG_ACC_MASK (DEVCG_ACC_MKNOD | DEVCG_ACC_READ | DEVCG_ACC_WRITE)
 
-#define DEV_BLOCK 1
-#define DEV_CHAR  2
-#define DEV_ALL   4  /* this represents all devices */
+#define DEVCG_DEV_BLOCK 1
+#define DEVCG_DEV_CHAR  2
+#define DEVCG_DEV_ALL   4  /* this represents all devices */
 
 static DEFINE_MUTEX(devcgroup_mutex);
 
@@ -245,21 +245,21 @@ static void set_access(char *acc, short access)
 {
 	int idx = 0;
 	memset(acc, 0, ACCLEN);
-	if (access & ACC_READ)
+	if (access & DEVCG_ACC_READ)
 		acc[idx++] = 'r';
-	if (access & ACC_WRITE)
+	if (access & DEVCG_ACC_WRITE)
 		acc[idx++] = 'w';
-	if (access & ACC_MKNOD)
+	if (access & DEVCG_ACC_MKNOD)
 		acc[idx++] = 'm';
 }
 
 static char type_to_char(short type)
 {
-	if (type == DEV_ALL)
+	if (type == DEVCG_DEV_ALL)
 		return 'a';
-	if (type == DEV_CHAR)
+	if (type == DEVCG_DEV_CHAR)
 		return 'c';
-	if (type == DEV_BLOCK)
+	if (type == DEVCG_DEV_BLOCK)
 		return 'b';
 	return 'X';
 }
@@ -286,10 +286,10 @@ static int devcgroup_seq_show(struct seq_file *m, void *v)
 	 * This way, the file remains as a "whitelist of devices"
 	 */
 	if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
-		set_access(acc, ACC_MASK);
+		set_access(acc, DEVCG_ACC_MASK);
 		set_majmin(maj, ~0);
 		set_majmin(min, ~0);
-		seq_printf(m, "%c %s:%s %s\n", type_to_char(DEV_ALL),
+		seq_printf(m, "%c %s:%s %s\n", type_to_char(DEVCG_DEV_ALL),
 			   maj, min, acc);
 	} else {
 		list_for_each_entry_rcu(ex, &devcgroup->exceptions, list) {
@@ -308,10 +308,10 @@ static int devcgroup_seq_show(struct seq_file *m, void *v)
 /**
  * match_exception	- iterates the exception list trying to find a complete match
  * @exceptions: list of exceptions
- * @type: device type (DEV_BLOCK or DEV_CHAR)
+ * @type: device type (DEVCG_DEV_BLOCK or DEVCG_DEV_CHAR)
  * @major: device file major number, ~0 to match all
  * @minor: device file minor number, ~0 to match all
- * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD)
+ * @access: permission mask (DEVCG_ACC_READ, DEVCG_ACC_WRITE, DEVCG_ACC_MKNOD)
  *
  * It is considered a complete match if an exception is found that will
  * contain the entire range of provided parameters.
@@ -324,9 +324,9 @@ static bool match_exception(struct list_head *exceptions, short type,
 	struct dev_exception_item *ex;
 
 	list_for_each_entry_rcu(ex, exceptions, list) {
-		if ((type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
+		if ((type & DEVCG_DEV_BLOCK) && !(ex->type & DEVCG_DEV_BLOCK))
 			continue;
-		if ((type & DEV_CHAR) && !(ex->type & DEV_CHAR))
+		if ((type & DEVCG_DEV_CHAR) && !(ex->type & DEVCG_DEV_CHAR))
 			continue;
 		if (ex->major != ~0 && ex->major != major)
 			continue;
@@ -343,10 +343,10 @@ static bool match_exception(struct list_head *exceptions, short type,
 /**
  * match_exception_partial - iterates the exception list trying to find a partial match
  * @exceptions: list of exceptions
- * @type: device type (DEV_BLOCK or DEV_CHAR)
+ * @type: device type (DEVCG_DEV_BLOCK or DEVCG_DEV_CHAR)
  * @major: device file major number, ~0 to match all
  * @minor: device file minor number, ~0 to match all
- * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD)
+ * @access: permission mask (DEVCG_ACC_READ, DEVCG_ACC_WRITE, DEVCG_ACC_MKNOD)
  *
  * It is considered a partial match if an exception's range is found to
  * contain *any* of the devices specified by provided parameters. This is
@@ -361,9 +361,9 @@ static bool match_exception_partial(struct list_head *exceptions, short type,
 	struct dev_exception_item *ex;
 
 	list_for_each_entry_rcu(ex, exceptions, list) {
-		if ((type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
+		if ((type & DEVCG_DEV_BLOCK) && !(ex->type & DEVCG_DEV_BLOCK))
 			continue;
-		if ((type & DEV_CHAR) && !(ex->type & DEV_CHAR))
+		if ((type & DEVCG_DEV_CHAR) && !(ex->type & DEVCG_DEV_CHAR))
 			continue;
 		/*
 		 * We must be sure that both the exception and the provided
@@ -646,10 +646,10 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
 		}
 		return 0;
 	case 'b':
-		ex.type = DEV_BLOCK;
+		ex.type = DEVCG_DEV_BLOCK;
 		break;
 	case 'c':
-		ex.type = DEV_CHAR;
+		ex.type = DEVCG_DEV_CHAR;
 		break;
 	default:
 		return -EINVAL;
@@ -702,13 +702,13 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
 	for (b++, count = 0; count < 3; count++, b++) {
 		switch (*b) {
 		case 'r':
-			ex.access |= ACC_READ;
+			ex.access |= DEVCG_ACC_READ;
 			break;
 		case 'w':
-			ex.access |= ACC_WRITE;
+			ex.access |= DEVCG_ACC_WRITE;
 			break;
 		case 'm':
-			ex.access |= ACC_MKNOD;
+			ex.access |= DEVCG_ACC_MKNOD;
 			break;
 		case '\n':
 		case '\0':
@@ -805,7 +805,7 @@ struct cgroup_subsys devices_cgrp_subsys = {
  * @type: device type
  * @major: device major number
  * @minor: device minor number
- * @access: combination of ACC_WRITE, ACC_READ and ACC_MKNOD
+ * @access: combination of DEVCG_ACC_WRITE, DEVCG_ACC_READ and DEVCG_ACC_MKNOD
  *
  * returns 0 on success, -EPERM case the operation is not permitted
  */
@@ -838,13 +838,13 @@ int __devcgroup_inode_permission(struct inode *inode, int mask)
 	short type, access = 0;
 
 	if (S_ISBLK(inode->i_mode))
-		type = DEV_BLOCK;
+		type = DEVCG_DEV_BLOCK;
 	if (S_ISCHR(inode->i_mode))
-		type = DEV_CHAR;
+		type = DEVCG_DEV_CHAR;
 	if (mask & MAY_WRITE)
-		access |= ACC_WRITE;
+		access |= DEVCG_ACC_WRITE;
 	if (mask & MAY_READ)
-		access |= ACC_READ;
+		access |= DEVCG_ACC_READ;
 
 	return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
 			access);
@@ -858,11 +858,11 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
 		return 0;
 
 	if (S_ISBLK(mode))
-		type = DEV_BLOCK;
+		type = DEVCG_DEV_BLOCK;
 	else
-		type = DEV_CHAR;
+		type = DEVCG_DEV_CHAR;
 
 	return __devcgroup_check_permission(type, MAJOR(dev), MINOR(dev),
-			ACC_MKNOD);
+			DEVCG_ACC_MKNOD);
 
 }
-- 
2.13.6

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

* [PATCH v2 net-next 2/5] device_cgroup: prepare code for bpf-based device controller
  2017-11-02 14:54 [PATCH v2 net-next 0/5] eBPF-based device cgroup controller Roman Gushchin
  2017-11-02 14:54 ` [PATCH v2 net-next 1/5] device_cgroup: add DEVCG_ prefix to ACC_* and DEV_* constants Roman Gushchin
@ 2017-11-02 14:54 ` Roman Gushchin
  2017-11-02 14:54 ` [PATCH v2 net-next 3/5] bpf, cgroup: implement eBPF-based device controller for cgroup v2 Roman Gushchin
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Roman Gushchin @ 2017-11-02 14:54 UTC (permalink / raw)
  To: netdev
  Cc: Tejun Heo, Alexei Starovoitov, Daniel Borkmann, linux-kernel,
	kernel-team, Roman Gushchin

This is non-functional change to prepare the device cgroup code
for adding eBPF-based controller for cgroups v2.

The patch performs the following changes:
1) __devcgroup_inode_permission() and devcgroup_inode_mknod()
   are moving to the device-cgroup.h and converting into static inline.
2) __devcgroup_check_permission() is exported.
3) devcgroup_check_permission() wrapper is introduced to be used
   by both existing and new bpf-based implementations.

Signed-off-by: Roman Gushchin <guro@fb.com>
Acked-by: Tejun Heo <tj@kernel.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 include/linux/device_cgroup.h | 61 ++++++++++++++++++++++++++++++++++++++++---
 security/device_cgroup.c      | 47 ++-------------------------------
 2 files changed, 59 insertions(+), 49 deletions(-)

diff --git a/include/linux/device_cgroup.h b/include/linux/device_cgroup.h
index 8b64221b432b..1e42d33accbf 100644
--- a/include/linux/device_cgroup.h
+++ b/include/linux/device_cgroup.h
@@ -1,16 +1,69 @@
 #include <linux/fs.h>
 
+#define DEVCG_ACC_MKNOD 1
+#define DEVCG_ACC_READ  2
+#define DEVCG_ACC_WRITE 4
+#define DEVCG_ACC_MASK (DEVCG_ACC_MKNOD | DEVCG_ACC_READ | DEVCG_ACC_WRITE)
+
+#define DEVCG_DEV_BLOCK 1
+#define DEVCG_DEV_CHAR  2
+#define DEVCG_DEV_ALL   4  /* this represents all devices */
+
+#ifdef CONFIG_CGROUP_DEVICE
+extern int __devcgroup_check_permission(short type, u32 major, u32 minor,
+					short access);
+#else
+static inline int __devcgroup_check_permission(short type, u32 major, u32 minor,
+					       short access)
+{ return 0; }
+#endif
+
 #ifdef CONFIG_CGROUP_DEVICE
-extern int __devcgroup_inode_permission(struct inode *inode, int mask);
-extern int devcgroup_inode_mknod(int mode, dev_t dev);
+static inline int devcgroup_check_permission(short type, u32 major, u32 minor,
+					     short access)
+{
+	return __devcgroup_check_permission(type, major, minor, access);
+}
+
 static inline int devcgroup_inode_permission(struct inode *inode, int mask)
 {
+	short type, access = 0;
+
 	if (likely(!inode->i_rdev))
 		return 0;
-	if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode))
+
+	if (S_ISBLK(inode->i_mode))
+		type = DEVCG_DEV_BLOCK;
+	else if (S_ISCHR(inode->i_mode))
+		type = DEVCG_DEV_CHAR;
+	else
 		return 0;
-	return __devcgroup_inode_permission(inode, mask);
+
+	if (mask & MAY_WRITE)
+		access |= DEVCG_ACC_WRITE;
+	if (mask & MAY_READ)
+		access |= DEVCG_ACC_READ;
+
+	return devcgroup_check_permission(type, imajor(inode), iminor(inode),
+					  access);
 }
+
+static inline int devcgroup_inode_mknod(int mode, dev_t dev)
+{
+	short type;
+
+	if (!S_ISBLK(mode) && !S_ISCHR(mode))
+		return 0;
+
+	if (S_ISBLK(mode))
+		type = DEVCG_DEV_BLOCK;
+	else
+		type = DEVCG_DEV_CHAR;
+
+	return devcgroup_check_permission(type, MAJOR(dev), MINOR(dev),
+					  DEVCG_ACC_MKNOD);
+}
+
 #else
 static inline int devcgroup_inode_permission(struct inode *inode, int mask)
 { return 0; }
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 76cc0cbbb10d..c54692208dcb 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -14,15 +14,6 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 
-#define DEVCG_ACC_MKNOD 1
-#define DEVCG_ACC_READ  2
-#define DEVCG_ACC_WRITE 4
-#define DEVCG_ACC_MASK (DEVCG_ACC_MKNOD | DEVCG_ACC_READ | DEVCG_ACC_WRITE)
-
-#define DEVCG_DEV_BLOCK 1
-#define DEVCG_DEV_CHAR  2
-#define DEVCG_DEV_ALL   4  /* this represents all devices */
-
 static DEFINE_MUTEX(devcgroup_mutex);
 
 enum devcg_behavior {
@@ -809,8 +800,8 @@ struct cgroup_subsys devices_cgrp_subsys = {
  *
  * returns 0 on success, -EPERM case the operation is not permitted
  */
-static int __devcgroup_check_permission(short type, u32 major, u32 minor,
-				        short access)
+int __devcgroup_check_permission(short type, u32 major, u32 minor,
+				 short access)
 {
 	struct dev_cgroup *dev_cgroup;
 	bool rc;
@@ -832,37 +823,3 @@ static int __devcgroup_check_permission(short type, u32 major, u32 minor,
 
 	return 0;
 }
-
-int __devcgroup_inode_permission(struct inode *inode, int mask)
-{
-	short type, access = 0;
-
-	if (S_ISBLK(inode->i_mode))
-		type = DEVCG_DEV_BLOCK;
-	if (S_ISCHR(inode->i_mode))
-		type = DEVCG_DEV_CHAR;
-	if (mask & MAY_WRITE)
-		access |= DEVCG_ACC_WRITE;
-	if (mask & MAY_READ)
-		access |= DEVCG_ACC_READ;
-
-	return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
-			access);
-}
-
-int devcgroup_inode_mknod(int mode, dev_t dev)
-{
-	short type;
-
-	if (!S_ISBLK(mode) && !S_ISCHR(mode))
-		return 0;
-
-	if (S_ISBLK(mode))
-		type = DEVCG_DEV_BLOCK;
-	else
-		type = DEVCG_DEV_CHAR;
-
-	return __devcgroup_check_permission(type, MAJOR(dev), MINOR(dev),
-			DEVCG_ACC_MKNOD);
-
-}
-- 
2.13.6

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

* [PATCH v2 net-next 3/5] bpf, cgroup: implement eBPF-based device controller for cgroup v2
  2017-11-02 14:54 [PATCH v2 net-next 0/5] eBPF-based device cgroup controller Roman Gushchin
  2017-11-02 14:54 ` [PATCH v2 net-next 1/5] device_cgroup: add DEVCG_ prefix to ACC_* and DEV_* constants Roman Gushchin
  2017-11-02 14:54 ` [PATCH v2 net-next 2/5] device_cgroup: prepare code for bpf-based device controller Roman Gushchin
@ 2017-11-02 14:54 ` Roman Gushchin
  2017-11-02 15:11   ` Alexei Starovoitov
  2017-11-02 14:54 ` [PATCH v2 net-next 4/5] bpf: move cgroup_helpers from samples/bpf/ to tools/testing/selftesting/bpf/ Roman Gushchin
  2017-11-02 14:54 ` [PATCH v2 net-next 5/5] selftests/bpf: add a test for device cgroup controller Roman Gushchin
  4 siblings, 1 reply; 8+ messages in thread
From: Roman Gushchin @ 2017-11-02 14:54 UTC (permalink / raw)
  To: netdev
  Cc: Tejun Heo, Alexei Starovoitov, Daniel Borkmann, linux-kernel,
	kernel-team, Roman Gushchin

Cgroup v2 lacks the device controller, provided by cgroup v1.
This patch adds a new eBPF program type, which in combination
of previously added ability to attach multiple eBPF programs
to a cgroup, will provide a similar functionality, but with some
additional flexibility.

This patch introduces a BPF_PROG_TYPE_CGROUP_DEVICE program type.
A program takes major and minor device numbers, device type
(block/character) and access type (mknod/read/write) as parameters
and returns an integer which defines if the operation should be
allowed or terminated with -EPERM.

Signed-off-by: Roman Gushchin <guro@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
 include/linux/bpf-cgroup.h     | 15 ++++++++++
 include/linux/bpf_types.h      |  3 ++
 include/linux/device_cgroup.h  |  8 ++++-
 include/uapi/linux/bpf.h       | 15 ++++++++++
 kernel/bpf/cgroup.c            | 67 ++++++++++++++++++++++++++++++++++++++++++
 kernel/bpf/syscall.c           |  7 +++++
 kernel/bpf/verifier.c          |  1 +
 tools/include/uapi/linux/bpf.h | 15 ++++++++++
 8 files changed, 130 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index 359b6f5d3d90..d77cefb3fe99 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -66,6 +66,9 @@ int __cgroup_bpf_run_filter_sock_ops(struct sock *sk,
 				     struct bpf_sock_ops_kern *sock_ops,
 				     enum bpf_attach_type type);
 
+int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor,
+				      short access, enum bpf_attach_type type);
+
 /* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */
 #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb)			      \
 ({									      \
@@ -111,6 +114,17 @@ int __cgroup_bpf_run_filter_sock_ops(struct sock *sk,
 	}								       \
 	__ret;								       \
 })
+
+#define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type, major, minor, access)	      \
+({									      \
+	int __ret = 0;							      \
+	if (cgroup_bpf_enabled)						      \
+		__ret = __cgroup_bpf_check_dev_permission(type, major, minor, \
+							  access,	      \
+							  BPF_CGROUP_DEVICE); \
+									      \
+	__ret;								      \
+})
 #else
 
 struct cgroup_bpf {};
@@ -121,6 +135,7 @@ static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; }
 #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; })
+#define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; })
 
 #endif /* CONFIG_CGROUP_BPF */
 
diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
index 36418ad43245..963a97ee4b7c 100644
--- a/include/linux/bpf_types.h
+++ b/include/linux/bpf_types.h
@@ -18,6 +18,9 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_KPROBE, kprobe)
 BPF_PROG_TYPE(BPF_PROG_TYPE_TRACEPOINT, tracepoint)
 BPF_PROG_TYPE(BPF_PROG_TYPE_PERF_EVENT, perf_event)
 #endif
+#ifdef CONFIG_CGROUP_BPF
+BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_DEVICE, cg_dev)
+#endif
 
 BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
 BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops)
diff --git a/include/linux/device_cgroup.h b/include/linux/device_cgroup.h
index 1e42d33accbf..90245a70d940 100644
--- a/include/linux/device_cgroup.h
+++ b/include/linux/device_cgroup.h
@@ -1,4 +1,5 @@
 #include <linux/fs.h>
+#include <linux/bpf-cgroup.h>
 
 #define DEVCG_ACC_MKNOD 1
 #define DEVCG_ACC_READ  2
@@ -18,10 +19,15 @@ static inline int __devcgroup_check_permission(short type, u32 major, u32 minor,
 { return 0; }
 #endif
 
-#ifdef CONFIG_CGROUP_DEVICE
+#if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF)
 static inline int devcgroup_check_permission(short type, u32 major, u32 minor,
 					     short access)
 {
+	int rc = BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type, major, minor, access);
+
+	if (rc)
+		return -EPERM;
+
 	return __devcgroup_check_permission(type, major, minor, access);
 }
 
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 0b7b54d898bd..4deb3c9acbb2 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -131,6 +131,7 @@ enum bpf_prog_type {
 	BPF_PROG_TYPE_LWT_XMIT,
 	BPF_PROG_TYPE_SOCK_OPS,
 	BPF_PROG_TYPE_SK_SKB,
+	BPF_PROG_TYPE_CGROUP_DEVICE,
 };
 
 enum bpf_attach_type {
@@ -140,6 +141,7 @@ enum bpf_attach_type {
 	BPF_CGROUP_SOCK_OPS,
 	BPF_SK_SKB_STREAM_PARSER,
 	BPF_SK_SKB_STREAM_VERDICT,
+	BPF_CGROUP_DEVICE,
 	__MAX_BPF_ATTACH_TYPE
 };
 
@@ -984,4 +986,17 @@ struct bpf_perf_event_value {
 	__u64 running;
 };
 
+#define DEV_BPF_ACC_MKNOD	(1ULL << 0)
+#define DEV_BPF_ACC_READ	(1ULL << 1)
+#define DEV_BPF_ACC_WRITE	(1ULL << 2)
+
+#define DEV_BPF_DEV_BLOCK	(1ULL << 0)
+#define DEV_BPF_DEV_CHAR	(1ULL << 1)
+
+struct bpf_cgroup_dev_ctx {
+	__u32 access_type; /* (access << 16) | type */
+	__u32 major;
+	__u32 minor;
+};
+
 #endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 3db5a17fcfe8..b789ab78d28f 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -522,3 +522,70 @@ int __cgroup_bpf_run_filter_sock_ops(struct sock *sk,
 	return ret == 1 ? 0 : -EPERM;
 }
 EXPORT_SYMBOL(__cgroup_bpf_run_filter_sock_ops);
+
+int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor,
+				      short access, enum bpf_attach_type type)
+{
+	struct cgroup *cgrp;
+	struct bpf_cgroup_dev_ctx ctx = {
+		.access_type = (access << 16) | dev_type,
+		.major = major,
+		.minor = minor,
+	};
+	int allow = 1;
+
+	rcu_read_lock();
+	cgrp = task_dfl_cgroup(current);
+	allow = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], &ctx,
+				   BPF_PROG_RUN);
+	rcu_read_unlock();
+
+	return !allow;
+}
+EXPORT_SYMBOL(__cgroup_bpf_check_dev_permission);
+
+static const struct bpf_func_proto *
+cgroup_dev_func_proto(enum bpf_func_id func_id)
+{
+	switch (func_id) {
+	case BPF_FUNC_map_lookup_elem:
+		return &bpf_map_lookup_elem_proto;
+	case BPF_FUNC_map_update_elem:
+		return &bpf_map_update_elem_proto;
+	case BPF_FUNC_map_delete_elem:
+		return &bpf_map_delete_elem_proto;
+	case BPF_FUNC_get_current_uid_gid:
+		return &bpf_get_current_uid_gid_proto;
+	case BPF_FUNC_trace_printk:
+		if (capable(CAP_SYS_ADMIN))
+			return bpf_get_trace_printk_proto();
+	default:
+		return NULL;
+	}
+}
+
+static bool cgroup_dev_is_valid_access(int off, int size,
+				       enum bpf_access_type type,
+				       struct bpf_insn_access_aux *info)
+{
+	if (type == BPF_WRITE)
+		return false;
+
+	if (off < 0 || off + size > sizeof(struct bpf_cgroup_dev_ctx))
+		return false;
+	/* The verifier guarantees that size > 0. */
+	if (off % size != 0)
+		return false;
+	if (size != sizeof(__u32))
+		return false;
+
+	return true;
+}
+
+const struct bpf_prog_ops cg_dev_prog_ops = {
+};
+
+const struct bpf_verifier_ops cg_dev_verifier_ops = {
+	.get_func_proto		= cgroup_dev_func_proto,
+	.is_valid_access	= cgroup_dev_is_valid_access,
+};
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 323be2473c4b..08f7b450828e 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1291,6 +1291,9 @@ static int bpf_prog_attach(const union bpf_attr *attr)
 	case BPF_CGROUP_SOCK_OPS:
 		ptype = BPF_PROG_TYPE_SOCK_OPS;
 		break;
+	case BPF_CGROUP_DEVICE:
+		ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
+		break;
 	case BPF_SK_SKB_STREAM_PARSER:
 	case BPF_SK_SKB_STREAM_VERDICT:
 		return sockmap_get_from_fd(attr, true);
@@ -1343,6 +1346,9 @@ static int bpf_prog_detach(const union bpf_attr *attr)
 	case BPF_CGROUP_SOCK_OPS:
 		ptype = BPF_PROG_TYPE_SOCK_OPS;
 		break;
+	case BPF_CGROUP_DEVICE:
+		ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
+		break;
 	case BPF_SK_SKB_STREAM_PARSER:
 	case BPF_SK_SKB_STREAM_VERDICT:
 		return sockmap_get_from_fd(attr, false);
@@ -1385,6 +1391,7 @@ static int bpf_prog_query(const union bpf_attr *attr,
 	case BPF_CGROUP_INET_EGRESS:
 	case BPF_CGROUP_INET_SOCK_CREATE:
 	case BPF_CGROUP_SOCK_OPS:
+	case BPF_CGROUP_DEVICE:
 		break;
 	default:
 		return -EINVAL;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 2bb6d6aa7085..811f0582a1cc 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3100,6 +3100,7 @@ static int check_return_code(struct bpf_verifier_env *env)
 	case BPF_PROG_TYPE_CGROUP_SKB:
 	case BPF_PROG_TYPE_CGROUP_SOCK:
 	case BPF_PROG_TYPE_SOCK_OPS:
+	case BPF_PROG_TYPE_CGROUP_DEVICE:
 		break;
 	default:
 		return 0;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 4a4b6e78c977..c0306ac49860 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -131,6 +131,7 @@ enum bpf_prog_type {
 	BPF_PROG_TYPE_LWT_XMIT,
 	BPF_PROG_TYPE_SOCK_OPS,
 	BPF_PROG_TYPE_SK_SKB,
+	BPF_PROG_TYPE_CGROUP_DEVICE,
 };
 
 enum bpf_attach_type {
@@ -140,6 +141,7 @@ enum bpf_attach_type {
 	BPF_CGROUP_SOCK_OPS,
 	BPF_SK_SKB_STREAM_PARSER,
 	BPF_SK_SKB_STREAM_VERDICT,
+	BPF_CGROUP_DEVICE,
 	__MAX_BPF_ATTACH_TYPE
 };
 
@@ -984,4 +986,17 @@ struct bpf_perf_event_value {
 	__u64 running;
 };
 
+#define DEV_BPF_ACC_MKNOD	(1ULL << 0)
+#define DEV_BPF_ACC_READ	(1ULL << 1)
+#define DEV_BPF_ACC_WRITE	(1ULL << 2)
+
+#define DEV_BPF_DEV_BLOCK	(1ULL << 0)
+#define DEV_BPF_DEV_CHAR	(1ULL << 1)
+
+struct bpf_cgroup_dev_ctx {
+	__u32 access_type; /* (access << 16) | type */
+	__u32 major;
+	__u32 minor;
+};
+
 #endif /* _UAPI__LINUX_BPF_H__ */
-- 
2.13.6

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

* [PATCH v2 net-next 4/5] bpf: move cgroup_helpers from samples/bpf/ to tools/testing/selftesting/bpf/
  2017-11-02 14:54 [PATCH v2 net-next 0/5] eBPF-based device cgroup controller Roman Gushchin
                   ` (2 preceding siblings ...)
  2017-11-02 14:54 ` [PATCH v2 net-next 3/5] bpf, cgroup: implement eBPF-based device controller for cgroup v2 Roman Gushchin
@ 2017-11-02 14:54 ` Roman Gushchin
  2017-11-02 14:54 ` [PATCH v2 net-next 5/5] selftests/bpf: add a test for device cgroup controller Roman Gushchin
  4 siblings, 0 replies; 8+ messages in thread
From: Roman Gushchin @ 2017-11-02 14:54 UTC (permalink / raw)
  To: netdev
  Cc: Tejun Heo, Alexei Starovoitov, Daniel Borkmann, linux-kernel,
	kernel-team, Roman Gushchin

The purpose of this move is to use these files in bpf tests.

Signed-off-by: Roman Gushchin <guro@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
 samples/bpf/Makefile                                      | 5 +++--
 tools/testing/selftests/bpf/Makefile                      | 2 +-
 {samples => tools/testing/selftests}/bpf/cgroup_helpers.c | 0
 {samples => tools/testing/selftests}/bpf/cgroup_helpers.h | 0
 4 files changed, 4 insertions(+), 3 deletions(-)
 rename {samples => tools/testing/selftests}/bpf/cgroup_helpers.c (100%)
 rename {samples => tools/testing/selftests}/bpf/cgroup_helpers.h (100%)

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index ea2b9e6135f3..adb1e5dba1ea 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -45,6 +45,7 @@ hostprogs-y += syscall_tp
 
 # Libbpf dependencies
 LIBBPF := ../../tools/lib/bpf/bpf.o
+CGROUP_HELPERS := ../../tools/testing/selftests/bpf/cgroup_helpers.o
 
 test_lru_dist-objs := test_lru_dist.o $(LIBBPF)
 sock_example-objs := sock_example.o $(LIBBPF)
@@ -68,13 +69,13 @@ map_perf_test-objs := bpf_load.o $(LIBBPF) map_perf_test_user.o
 test_overhead-objs := bpf_load.o $(LIBBPF) test_overhead_user.o
 test_cgrp2_array_pin-objs := $(LIBBPF) test_cgrp2_array_pin.o
 test_cgrp2_attach-objs := $(LIBBPF) test_cgrp2_attach.o
-test_cgrp2_attach2-objs := $(LIBBPF) test_cgrp2_attach2.o cgroup_helpers.o
+test_cgrp2_attach2-objs := $(LIBBPF) test_cgrp2_attach2.o $(CGROUP_HELPERS)
 test_cgrp2_sock-objs := $(LIBBPF) test_cgrp2_sock.o
 test_cgrp2_sock2-objs := bpf_load.o $(LIBBPF) test_cgrp2_sock2.o
 xdp1-objs := bpf_load.o $(LIBBPF) xdp1_user.o
 # reuse xdp1 source intentionally
 xdp2-objs := bpf_load.o $(LIBBPF) xdp1_user.o
-test_current_task_under_cgroup-objs := bpf_load.o $(LIBBPF) cgroup_helpers.o \
+test_current_task_under_cgroup-objs := bpf_load.o $(LIBBPF) $(CGROUP_HELPERS) \
 				       test_current_task_under_cgroup_user.o
 trace_event-objs := bpf_load.o $(LIBBPF) trace_event_user.o
 sampleip-objs := bpf_load.o $(LIBBPF) sampleip_user.o
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 2e7880ea0add..36c34f0218a3 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -22,7 +22,7 @@ TEST_PROGS := test_kmod.sh test_xdp_redirect.sh test_xdp_meta.sh
 
 include ../lib.mk
 
-BPFOBJ := $(OUTPUT)/libbpf.a
+BPFOBJ := $(OUTPUT)/libbpf.a $(OUTPUT)/cgroup_helpers.c
 
 $(TEST_GEN_PROGS): $(BPFOBJ)
 
diff --git a/samples/bpf/cgroup_helpers.c b/tools/testing/selftests/bpf/cgroup_helpers.c
similarity index 100%
rename from samples/bpf/cgroup_helpers.c
rename to tools/testing/selftests/bpf/cgroup_helpers.c
diff --git a/samples/bpf/cgroup_helpers.h b/tools/testing/selftests/bpf/cgroup_helpers.h
similarity index 100%
rename from samples/bpf/cgroup_helpers.h
rename to tools/testing/selftests/bpf/cgroup_helpers.h
-- 
2.13.6

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

* [PATCH v2 net-next 5/5] selftests/bpf: add a test for device cgroup controller
  2017-11-02 14:54 [PATCH v2 net-next 0/5] eBPF-based device cgroup controller Roman Gushchin
                   ` (3 preceding siblings ...)
  2017-11-02 14:54 ` [PATCH v2 net-next 4/5] bpf: move cgroup_helpers from samples/bpf/ to tools/testing/selftesting/bpf/ Roman Gushchin
@ 2017-11-02 14:54 ` Roman Gushchin
  4 siblings, 0 replies; 8+ messages in thread
From: Roman Gushchin @ 2017-11-02 14:54 UTC (permalink / raw)
  To: netdev
  Cc: Tejun Heo, Alexei Starovoitov, Daniel Borkmann, linux-kernel,
	kernel-team, Roman Gushchin

Add a test for device cgroup controller.

The test loads a simple bpf program which logs all
device access attempts using trace_printk() and forbids
all operations except operations with /dev/zero and
/dev/urandom.

Then the test creates and joins a test cgroup, and attaches
the bpf program to it.

Then it tries to perform some simple device operations
and checks the result:

  create /dev/null (should fail)
  create /dev/zero (should pass)
  copy data from /dev/urandom to /dev/zero (should pass)
  copy data from /dev/urandom to /dev/full (should fail)
  copy data from /dev/random to /dev/zero (should fail)

Signed-off-by: Roman Gushchin <guro@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
 tools/testing/selftests/bpf/Makefile          |  4 +-
 tools/testing/selftests/bpf/dev_cgroup.c      | 60 +++++++++++++++++
 tools/testing/selftests/bpf/test_dev_cgroup.c | 93 +++++++++++++++++++++++++++
 3 files changed, 155 insertions(+), 2 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/dev_cgroup.c
 create mode 100644 tools/testing/selftests/bpf/test_dev_cgroup.c

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 36c34f0218a3..64ba3684a4f4 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -12,11 +12,11 @@ CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../i
 LDLIBS += -lcap -lelf
 
 TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
-	test_align test_verifier_log
+	test_align test_verifier_log test_dev_cgroup
 
 TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
 	test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o     \
-	sockmap_verdict_prog.o
+	sockmap_verdict_prog.o dev_cgroup.o
 
 TEST_PROGS := test_kmod.sh test_xdp_redirect.sh test_xdp_meta.sh
 
diff --git a/tools/testing/selftests/bpf/dev_cgroup.c b/tools/testing/selftests/bpf/dev_cgroup.c
new file mode 100644
index 000000000000..f15d5befa099
--- /dev/null
+++ b/tools/testing/selftests/bpf/dev_cgroup.c
@@ -0,0 +1,60 @@
+/* Copyright (c) 2017 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/bpf.h>
+#include <linux/version.h>
+#include "bpf_helpers.h"
+
+SEC("cgroup/dev")
+int bpf_prog1(struct bpf_cgroup_dev_ctx *ctx)
+{
+	short type = ctx->access_type & 0xFFFF;
+#ifdef DEBUG
+	short access = ctx->access_type >> 16;
+	char fmt[] = "  %d:%d    \n";
+
+	switch (type) {
+	case DEV_BPF_DEV_BLOCK:
+		fmt[0] = 'b';
+		break;
+	case DEV_BPF_DEV_CHAR:
+		fmt[0] = 'c';
+		break;
+	default:
+		fmt[0] = '?';
+		break;
+	}
+
+	if (access & DEV_BPF_ACC_READ)
+		fmt[8] = 'r';
+
+	if (access & DEV_BPF_ACC_WRITE)
+		fmt[9] = 'w';
+
+	if (access & DEV_BPF_ACC_MKNOD)
+		fmt[10] = 'm';
+
+	bpf_trace_printk(fmt, sizeof(fmt), ctx->major, ctx->minor);
+#endif
+
+	/* Allow access to /dev/zero and /dev/random.
+	 * Forbid everything else.
+	 */
+	if (ctx->major != 1 || type != DEV_BPF_DEV_CHAR)
+		return 0;
+
+	switch (ctx->minor) {
+	case 5: /* 1:5 /dev/zero */
+	case 9: /* 1:9 /dev/urandom */
+		return 1;
+	}
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
+__u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/testing/selftests/bpf/test_dev_cgroup.c b/tools/testing/selftests/bpf/test_dev_cgroup.c
new file mode 100644
index 000000000000..02c85d6c89b0
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_dev_cgroup.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 2017 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <linux/bpf.h>
+#include <bpf/bpf.h>
+#include <bpf/libbpf.h>
+
+#include "cgroup_helpers.h"
+
+#define DEV_CGROUP_PROG "./dev_cgroup.o"
+
+#define TEST_CGROUP "test-bpf-based-device-cgroup/"
+
+int main(int argc, char **argv)
+{
+	struct bpf_object *obj;
+	int error = EXIT_FAILURE;
+	int prog_fd, cgroup_fd;
+	__u32 prog_cnt;
+
+	if (bpf_prog_load(DEV_CGROUP_PROG, BPF_PROG_TYPE_CGROUP_DEVICE,
+			  &obj, &prog_fd)) {
+		printf("Failed to load DEV_CGROUP program\n");
+		goto err;
+	}
+
+	if (setup_cgroup_environment()) {
+		printf("Failed to load DEV_CGROUP program\n");
+		goto err;
+	}
+
+	/* Create a cgroup, get fd, and join it */
+	cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
+	if (!cgroup_fd) {
+		printf("Failed to create test cgroup\n");
+		goto err;
+	}
+
+	if (join_cgroup(TEST_CGROUP)) {
+		printf("Failed to join cgroup\n");
+		goto err;
+	}
+
+	/* Attach bpf program */
+	if (bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE, 0)) {
+		printf("Failed to attach DEV_CGROUP program");
+		goto err;
+	}
+
+	if (bpf_prog_query(cgroup_fd, BPF_CGROUP_DEVICE, 0, NULL, NULL,
+			   &prog_cnt)) {
+		printf("Failed to query attached programs");
+		goto err;
+	}
+
+	/* All operations with /dev/zero and and /dev/urandom are allowed,
+	 * everything else is forbidden.
+	 */
+	assert(system("rm -f /tmp/test_dev_cgroup_null") == 0);
+	assert(system("mknod /tmp/test_dev_cgroup_null c 1 3"));
+	assert(system("rm -f /tmp/test_dev_cgroup_null") == 0);
+
+	/* /dev/zero is whitelisted */
+	assert(system("rm -f /tmp/test_dev_cgroup_zero") == 0);
+	assert(system("mknod /tmp/test_dev_cgroup_zero c 1 5") == 0);
+	assert(system("rm -f /tmp/test_dev_cgroup_zero") == 0);
+
+	assert(system("dd if=/dev/urandom of=/dev/zero count=64") == 0);
+
+	/* src is allowed, target is forbidden */
+	assert(system("dd if=/dev/urandom of=/dev/full count=64"));
+
+	/* src is forbidden, target is allowed */
+	assert(system("dd if=/dev/random of=/dev/zero count=64"));
+
+	error = 0;
+	printf("test_dev_cgroup:PASS\n");
+
+err:
+	cleanup_cgroup_environment();
+
+	return error;
+}
-- 
2.13.6

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

* Re: [PATCH v2 net-next 3/5] bpf, cgroup: implement eBPF-based device controller for cgroup v2
  2017-11-02 14:54 ` [PATCH v2 net-next 3/5] bpf, cgroup: implement eBPF-based device controller for cgroup v2 Roman Gushchin
@ 2017-11-02 15:11   ` Alexei Starovoitov
  2017-11-02 16:51     ` Roman Gushchin
  0 siblings, 1 reply; 8+ messages in thread
From: Alexei Starovoitov @ 2017-11-02 15:11 UTC (permalink / raw)
  To: Roman Gushchin, netdev
  Cc: Tejun Heo, Alexei Starovoitov, Daniel Borkmann, linux-kernel,
	kernel-team

On 11/2/17 7:54 AM, Roman Gushchin wrote:
> +#define DEV_BPF_ACC_MKNOD	(1ULL << 0)
> +#define DEV_BPF_ACC_READ	(1ULL << 1)
> +#define DEV_BPF_ACC_WRITE	(1ULL << 2)
> +
> +#define DEV_BPF_DEV_BLOCK	(1ULL << 0)
> +#define DEV_BPF_DEV_CHAR	(1ULL << 1)
> +

all macros in bpf.h start with BPF_
To be consistent with the rest can you rename above to BPF_DEVCG_.. ?

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

* Re: [PATCH v2 net-next 3/5] bpf, cgroup: implement eBPF-based device controller for cgroup v2
  2017-11-02 15:11   ` Alexei Starovoitov
@ 2017-11-02 16:51     ` Roman Gushchin
  0 siblings, 0 replies; 8+ messages in thread
From: Roman Gushchin @ 2017-11-02 16:51 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: netdev, Tejun Heo, Alexei Starovoitov, Daniel Borkmann,
	linux-kernel, kernel-team

On Thu, Nov 02, 2017 at 08:11:07AM -0700, Alexei Starovoitov wrote:
> On 11/2/17 7:54 AM, Roman Gushchin wrote:
> > +#define DEV_BPF_ACC_MKNOD	(1ULL << 0)
> > +#define DEV_BPF_ACC_READ	(1ULL << 1)
> > +#define DEV_BPF_ACC_WRITE	(1ULL << 2)
> > +
> > +#define DEV_BPF_DEV_BLOCK	(1ULL << 0)
> > +#define DEV_BPF_DEV_CHAR	(1ULL << 1)
> > +
> 
> all macros in bpf.h start with BPF_
> To be consistent with the rest can you rename above to BPF_DEVCG_.. ?

Sure. Will post v3.

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

end of thread, other threads:[~2017-11-02 16:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-02 14:54 [PATCH v2 net-next 0/5] eBPF-based device cgroup controller Roman Gushchin
2017-11-02 14:54 ` [PATCH v2 net-next 1/5] device_cgroup: add DEVCG_ prefix to ACC_* and DEV_* constants Roman Gushchin
2017-11-02 14:54 ` [PATCH v2 net-next 2/5] device_cgroup: prepare code for bpf-based device controller Roman Gushchin
2017-11-02 14:54 ` [PATCH v2 net-next 3/5] bpf, cgroup: implement eBPF-based device controller for cgroup v2 Roman Gushchin
2017-11-02 15:11   ` Alexei Starovoitov
2017-11-02 16:51     ` Roman Gushchin
2017-11-02 14:54 ` [PATCH v2 net-next 4/5] bpf: move cgroup_helpers from samples/bpf/ to tools/testing/selftesting/bpf/ Roman Gushchin
2017-11-02 14:54 ` [PATCH v2 net-next 5/5] selftests/bpf: add a test for device cgroup controller Roman Gushchin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.