[bpf-next,v4,3/8] bpf: Introduce task open coded iterator kfuncs
Commit Message
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
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
@@ -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)
@@ -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)
@@ -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