[bpf-next,v4,3/8] bpf: Introduce task open coded iterator kfuncs

Message ID 20231007124522.34834-4-zhouchuyi@bytedance.com
State New
Headers
Series Add Open-coded task, css_task and css iters |

Commit Message

Chuyi Zhou Oct. 7, 2023, 12:45 p.m. UTC
  This patch adds kfuncs bpf_iter_task_{new,next,destroy} which allow
creation and manipulation of struct bpf_iter_task in open-coded iterator
style. BPF programs can use these kfuncs or through bpf_for_each macro to
iterate all processes in the system.

The API design keep consistent with SEC("iter/task"). bpf_iter_task_new()
accepts a specific task and iterating type which allows:

1. iterating all process in the system(BPF_TASK_ITER_ALL_PROCS)

2. iterating all threads in the system(BPF_TASK_ITER_ALL_THREADS)

3. iterating all threads of a specific task(BPF_TASK_ITER_PROC_THREADS)

Signed-off-by: Chuyi Zhou <zhouchuyi@bytedance.com>
---
 kernel/bpf/helpers.c                          |  3 +
 kernel/bpf/task_iter.c                        | 82 +++++++++++++++++++
 .../testing/selftests/bpf/bpf_experimental.h  |  5 ++
 3 files changed, 90 insertions(+)
  

Comments

kernel test robot Oct. 7, 2023, 3:22 p.m. UTC | #1
Hi Chuyi,

kernel test robot noticed the following build warnings:

[auto build test WARNING on bpf-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Chuyi-Zhou/cgroup-Prepare-for-using-css_task_iter_-in-BPF/20231007-204750
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
patch link:    https://lore.kernel.org/r/20231007124522.34834-4-zhouchuyi%40bytedance.com
patch subject: [PATCH bpf-next v4 3/8] bpf: Introduce task open coded iterator kfuncs
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20231007/202310072354.0oARP80g-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231007/202310072354.0oARP80g-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202310072354.0oARP80g-lkp@intel.com/

All warnings (new ones prefixed by >>):

   kernel/bpf/task_iter.c:815:17: warning: no previous prototype for 'bpf_iter_css_task_new' [-Wmissing-prototypes]
     815 | __bpf_kfunc int bpf_iter_css_task_new(struct bpf_iter_css_task *it,
         |                 ^~~~~~~~~~~~~~~~~~~~~
   kernel/bpf/task_iter.c:840:33: warning: no previous prototype for 'bpf_iter_css_task_next' [-Wmissing-prototypes]
     840 | __bpf_kfunc struct task_struct *bpf_iter_css_task_next(struct bpf_iter_css_task *it)
         |                                 ^~~~~~~~~~~~~~~~~~~~~~
   kernel/bpf/task_iter.c:849:18: warning: no previous prototype for 'bpf_iter_css_task_destroy' [-Wmissing-prototypes]
     849 | __bpf_kfunc void bpf_iter_css_task_destroy(struct bpf_iter_css_task *it)
         |                  ^~~~~~~~~~~~~~~~~~~~~~~~~
>> kernel/bpf/task_iter.c:875:17: warning: no previous prototype for 'bpf_iter_task_new' [-Wmissing-prototypes]
     875 | __bpf_kfunc int bpf_iter_task_new(struct bpf_iter_task *it,
         |                 ^~~~~~~~~~~~~~~~~
>> kernel/bpf/task_iter.c:903:33: warning: no previous prototype for 'bpf_iter_task_next' [-Wmissing-prototypes]
     903 | __bpf_kfunc struct task_struct *bpf_iter_task_next(struct bpf_iter_task *it)
         |                                 ^~~~~~~~~~~~~~~~~~
>> kernel/bpf/task_iter.c:937:18: warning: no previous prototype for 'bpf_iter_task_destroy' [-Wmissing-prototypes]
     937 | __bpf_kfunc void bpf_iter_task_destroy(struct bpf_iter_task *it)
         |                  ^~~~~~~~~~~~~~~~~~~~~
   In file included from <command-line>:
   kernel/bpf/task_iter.c: In function 'bpf_iter_task_new':
   include/linux/compiler_types.h:425:45: error: call to '__compiletime_assert_438' declared with attribute error: BUILD_BUG_ON failed: sizeof(struct bpf_iter_task_kern) != sizeof(struct bpf_iter_task)
     425 |         _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
         |                                             ^
   include/linux/compiler_types.h:406:25: note: in definition of macro '__compiletime_assert'
     406 |                         prefix ## suffix();                             \
         |                         ^~~~~~
   include/linux/compiler_types.h:425:9: note: in expansion of macro '_compiletime_assert'
     425 |         _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
         |         ^~~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
      39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
         |                                     ^~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:50:9: note: in expansion of macro 'BUILD_BUG_ON_MSG'
      50 |         BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
         |         ^~~~~~~~~~~~~~~~
   kernel/bpf/task_iter.c:880:9: note: in expansion of macro 'BUILD_BUG_ON'
     880 |         BUILD_BUG_ON(sizeof(struct bpf_iter_task_kern) != sizeof(struct bpf_iter_task));
         |         ^~~~~~~~~~~~


vim +/bpf_iter_task_new +875 kernel/bpf/task_iter.c

   814	
 > 815	__bpf_kfunc int bpf_iter_css_task_new(struct bpf_iter_css_task *it,
   816			struct cgroup_subsys_state *css, unsigned int flags)
   817	{
   818		struct bpf_iter_css_task_kern *kit = (void *)it;
   819	
   820		BUILD_BUG_ON(sizeof(struct bpf_iter_css_task_kern) != sizeof(struct bpf_iter_css_task));
   821		BUILD_BUG_ON(__alignof__(struct bpf_iter_css_task_kern) !=
   822						__alignof__(struct bpf_iter_css_task));
   823		kit->css_it = NULL;
   824		switch (flags) {
   825		case CSS_TASK_ITER_PROCS | CSS_TASK_ITER_THREADED:
   826		case CSS_TASK_ITER_PROCS:
   827		case 0:
   828			break;
   829		default:
   830			return -EINVAL;
   831		}
   832	
   833		kit->css_it = bpf_mem_alloc(&bpf_global_ma, sizeof(struct css_task_iter));
   834		if (!kit->css_it)
   835			return -ENOMEM;
   836		css_task_iter_start(css, flags, kit->css_it);
   837		return 0;
   838	}
   839	
 > 840	__bpf_kfunc struct task_struct *bpf_iter_css_task_next(struct bpf_iter_css_task *it)
   841	{
   842		struct bpf_iter_css_task_kern *kit = (void *)it;
   843	
   844		if (!kit->css_it)
   845			return NULL;
   846		return css_task_iter_next(kit->css_it);
   847	}
   848	
 > 849	__bpf_kfunc void bpf_iter_css_task_destroy(struct bpf_iter_css_task *it)
   850	{
   851		struct bpf_iter_css_task_kern *kit = (void *)it;
   852	
   853		if (!kit->css_it)
   854			return;
   855		css_task_iter_end(kit->css_it);
   856		bpf_mem_free(&bpf_global_ma, kit->css_it);
   857	}
   858	
   859	struct bpf_iter_task {
   860		__u64 __opaque[3];
   861	} __attribute__((aligned(8)));
   862	
   863	struct bpf_iter_task_kern {
   864		struct task_struct *task;
   865		struct task_struct *pos;
   866		unsigned int flags;
   867	} __attribute__((aligned(8)));
   868	
   869	enum {
   870		BPF_TASK_ITER_ALL_PROCS,
   871		BPF_TASK_ITER_ALL_THREADS,
   872		BPF_TASK_ITER_PROC_THREADS
   873	};
   874	
 > 875	__bpf_kfunc int bpf_iter_task_new(struct bpf_iter_task *it,
   876			struct task_struct *task, unsigned int flags)
   877	{
   878		struct bpf_iter_task_kern *kit = (void *)it;
   879	
   880		BUILD_BUG_ON(sizeof(struct bpf_iter_task_kern) != sizeof(struct bpf_iter_task));
   881		BUILD_BUG_ON(__alignof__(struct bpf_iter_task_kern) !=
   882						__alignof__(struct bpf_iter_task));
   883	
   884		kit->task = kit->pos = NULL;
   885		switch (flags) {
   886		case BPF_TASK_ITER_ALL_THREADS:
   887		case BPF_TASK_ITER_ALL_PROCS:
   888		case BPF_TASK_ITER_PROC_THREADS:
   889			break;
   890		default:
   891			return -EINVAL;
   892		}
   893	
   894		if (flags == BPF_TASK_ITER_PROC_THREADS)
   895			kit->task = task;
   896		else
   897			kit->task = &init_task;
   898		kit->pos = kit->task;
   899		kit->flags = flags;
   900		return 0;
   901	}
   902	
 > 903	__bpf_kfunc struct task_struct *bpf_iter_task_next(struct bpf_iter_task *it)
   904	{
   905		struct bpf_iter_task_kern *kit = (void *)it;
   906		struct task_struct *pos;
   907		unsigned int flags;
   908	
   909		flags = kit->flags;
   910		pos = kit->pos;
   911	
   912		if (!pos)
   913			goto out;
   914	
   915		if (flags == BPF_TASK_ITER_ALL_PROCS)
   916			goto get_next_task;
   917	
   918		kit->pos = next_thread(kit->pos);
   919		if (kit->pos == kit->task) {
   920			if (flags == BPF_TASK_ITER_PROC_THREADS) {
   921				kit->pos = NULL;
   922				goto out;
   923			}
   924		} else
   925			goto out;
   926	
   927	get_next_task:
   928		kit->pos = next_task(kit->pos);
   929		kit->task = kit->pos;
   930		if (kit->pos == &init_task)
   931			kit->pos = NULL;
   932	
   933	out:
   934		return pos;
   935	}
   936	
 > 937	__bpf_kfunc void bpf_iter_task_destroy(struct bpf_iter_task *it)
   938	{
   939	}
   940
  

Patch

diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 8699cabb52b2..8111437a999e 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -2552,6 +2552,9 @@  BTF_ID_FLAGS(func, bpf_iter_num_destroy, KF_ITER_DESTROY)
 BTF_ID_FLAGS(func, bpf_iter_css_task_new, KF_ITER_NEW | KF_TRUSTED_ARGS)
 BTF_ID_FLAGS(func, bpf_iter_css_task_next, KF_ITER_NEXT | KF_RET_NULL)
 BTF_ID_FLAGS(func, bpf_iter_css_task_destroy, KF_ITER_DESTROY)
+BTF_ID_FLAGS(func, bpf_iter_task_new, KF_ITER_NEW | KF_TRUSTED_ARGS)
+BTF_ID_FLAGS(func, bpf_iter_task_next, KF_ITER_NEXT | KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_iter_task_destroy, KF_ITER_DESTROY)
 BTF_ID_FLAGS(func, bpf_dynptr_adjust)
 BTF_ID_FLAGS(func, bpf_dynptr_is_null)
 BTF_ID_FLAGS(func, bpf_dynptr_is_rdonly)
diff --git a/kernel/bpf/task_iter.c b/kernel/bpf/task_iter.c
index 2cfcb4dd8a37..c2e1c3cbffea 100644
--- a/kernel/bpf/task_iter.c
+++ b/kernel/bpf/task_iter.c
@@ -856,6 +856,88 @@  __bpf_kfunc void bpf_iter_css_task_destroy(struct bpf_iter_css_task *it)
 	bpf_mem_free(&bpf_global_ma, kit->css_it);
 }
 
+struct bpf_iter_task {
+	__u64 __opaque[3];
+} __attribute__((aligned(8)));
+
+struct bpf_iter_task_kern {
+	struct task_struct *task;
+	struct task_struct *pos;
+	unsigned int flags;
+} __attribute__((aligned(8)));
+
+enum {
+	BPF_TASK_ITER_ALL_PROCS,
+	BPF_TASK_ITER_ALL_THREADS,
+	BPF_TASK_ITER_PROC_THREADS
+};
+
+__bpf_kfunc int bpf_iter_task_new(struct bpf_iter_task *it,
+		struct task_struct *task, unsigned int flags)
+{
+	struct bpf_iter_task_kern *kit = (void *)it;
+
+	BUILD_BUG_ON(sizeof(struct bpf_iter_task_kern) != sizeof(struct bpf_iter_task));
+	BUILD_BUG_ON(__alignof__(struct bpf_iter_task_kern) !=
+					__alignof__(struct bpf_iter_task));
+
+	kit->task = kit->pos = NULL;
+	switch (flags) {
+	case BPF_TASK_ITER_ALL_THREADS:
+	case BPF_TASK_ITER_ALL_PROCS:
+	case BPF_TASK_ITER_PROC_THREADS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (flags == BPF_TASK_ITER_PROC_THREADS)
+		kit->task = task;
+	else
+		kit->task = &init_task;
+	kit->pos = kit->task;
+	kit->flags = flags;
+	return 0;
+}
+
+__bpf_kfunc struct task_struct *bpf_iter_task_next(struct bpf_iter_task *it)
+{
+	struct bpf_iter_task_kern *kit = (void *)it;
+	struct task_struct *pos;
+	unsigned int flags;
+
+	flags = kit->flags;
+	pos = kit->pos;
+
+	if (!pos)
+		goto out;
+
+	if (flags == BPF_TASK_ITER_ALL_PROCS)
+		goto get_next_task;
+
+	kit->pos = next_thread(kit->pos);
+	if (kit->pos == kit->task) {
+		if (flags == BPF_TASK_ITER_PROC_THREADS) {
+			kit->pos = NULL;
+			goto out;
+		}
+	} else
+		goto out;
+
+get_next_task:
+	kit->pos = next_task(kit->pos);
+	kit->task = kit->pos;
+	if (kit->pos == &init_task)
+		kit->pos = NULL;
+
+out:
+	return pos;
+}
+
+__bpf_kfunc void bpf_iter_task_destroy(struct bpf_iter_task *it)
+{
+}
+
 DEFINE_PER_CPU(struct mmap_unlock_irq_work, mmap_unlock_work);
 
 static void do_mmap_read_unlock(struct irq_work *entry)
diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index 8b53537e0f27..1ec82997cce7 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -457,5 +457,10 @@  extern int bpf_iter_css_task_new(struct bpf_iter_css_task *it,
 extern struct task_struct *bpf_iter_css_task_next(struct bpf_iter_css_task *it) __weak __ksym;
 extern void bpf_iter_css_task_destroy(struct bpf_iter_css_task *it) __weak __ksym;
 
+struct bpf_iter_task;
+extern int bpf_iter_task_new(struct bpf_iter_task *it,
+		struct task_struct *task, unsigned int flags) __weak __ksym;
+extern struct task_struct *bpf_iter_task_next(struct bpf_iter_task *it) __weak __ksym;
+extern void bpf_iter_task_destroy(struct bpf_iter_task *it) __weak __ksym;
 
 #endif