* Re: [PATCH RFC bpf-next v1 5/8] bpf: Introduce a new program type bpf_view.
@ 2022-01-10 7:06 kernel test robot
0 siblings, 0 replies; 3+ messages in thread
From: kernel test robot @ 2022-01-10 7:06 UTC (permalink / raw)
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 15611 bytes --]
CC: llvm(a)lists.linux.dev
CC: kbuild-all(a)lists.01.org
In-Reply-To: <20220106215059.2308931-6-haoluo@google.com>
References: <20220106215059.2308931-6-haoluo@google.com>
TO: Hao Luo <haoluo@google.com>
Hi Hao,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on bpf-next/master]
url: https://github.com/0day-ci/linux/commits/Hao-Luo/Pinning-bpf-objects-outside-bpffs/20220107-055252
base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
:::::: branch date: 3 days ago
:::::: commit date: 3 days ago
config: arm-randconfig-c002-20220107 (https://download.01.org/0day-ci/archive/20220110/202201101429.2XquVD3A-lkp(a)intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 32167bfe64a4c5dd4eb3f7a58e24f4cba76f5ac2)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install arm cross compiling tool for clang build
# apt-get install binutils-arm-linux-gnueabi
# https://github.com/0day-ci/linux/commit/f3a5b66e45ed0d7bdc610cce2e0b6a3c606dbb95
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Hao-Luo/Pinning-bpf-objects-outside-bpffs/20220107-055252
git checkout f3a5b66e45ed0d7bdc610cce2e0b6a3c606dbb95
# save the config file to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm clang-analyzer
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
clang-analyzer warnings: (new ones prefixed by >>)
fs/ext4/mballoc.c:5817:3: note: Value stored to 'err' is never read
err = PTR_ERR(bitmap_bh);
^ ~~~~~~~~~~~~~~~~~~
Suppressed 2 warnings (2 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
2 warnings generated.
fs/xfs/libxfs/xfs_attr.c:1243:2: warning: Value stored to 'error' is never read [clang-analyzer-deadcode.DeadStores]
error = xfs_attr_node_removename(args, state);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fs/xfs/libxfs/xfs_attr.c:1243:2: note: Value stored to 'error' is never read
error = xfs_attr_node_removename(args, state);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
3 warnings generated.
fs/xfs/libxfs/xfs_attr_leaf.c:2243:29: warning: Value stored to 'drop_leaf' during its initialization is never read [clang-analyzer-deadcode.DeadStores]
struct xfs_attr_leafblock *drop_leaf = drop_blk->bp->b_addr;
^~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
fs/xfs/libxfs/xfs_attr_leaf.c:2243:29: note: Value stored to 'drop_leaf' during its initialization is never read
struct xfs_attr_leafblock *drop_leaf = drop_blk->bp->b_addr;
^~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
fs/xfs/libxfs/xfs_attr_leaf.c:2244:29: warning: Value stored to 'save_leaf' during its initialization is never read [clang-analyzer-deadcode.DeadStores]
struct xfs_attr_leafblock *save_leaf = save_blk->bp->b_addr;
^~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
fs/xfs/libxfs/xfs_attr_leaf.c:2244:29: note: Value stored to 'save_leaf' during its initialization is never read
struct xfs_attr_leafblock *save_leaf = save_blk->bp->b_addr;
^~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
4 warnings generated.
fs/xfs/xfs_reflink.c:1151:3: warning: Value stored to 'qdelta' is never read [clang-analyzer-deadcode.DeadStores]
qdelta += dmap->br_blockcount;
^ ~~~~~~~~~~~~~~~~~~~
fs/xfs/xfs_reflink.c:1151:3: note: Value stored to 'qdelta' is never read
qdelta += dmap->br_blockcount;
^ ~~~~~~~~~~~~~~~~~~~
fs/xfs/xfs_reflink.c:1326:2: warning: Value stored to 'ret' is never read [clang-analyzer-deadcode.DeadStores]
ret = -EINVAL;
^ ~~~~~~~
fs/xfs/xfs_reflink.c:1326:2: note: Value stored to 'ret' is never read
ret = -EINVAL;
^ ~~~~~~~
Suppressed 2 warnings (1 in non-user code, 1 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
drivers/clk/clk-max9485.c:199:9: warning: Access to field 'out' results in a dereference of a null pointer (loaded from variable 'prev') [clang-analyzer-core.NullDereference]
return prev->out;
^~~~
drivers/clk/clk-max9485.c:165:36: note: 'prev' initialized to a null pointer value
const struct max9485_rate *curr, *prev = NULL;
^~~~
drivers/clk/clk-max9485.c:167:29: note: Assuming field 'out' is equal to 0
for (curr = max9485_rates; curr->out != 0; curr++) {
^~~~~~~~~~~~~~
drivers/clk/clk-max9485.c:167:2: note: Loop condition is false. Execution continues on line 199
for (curr = max9485_rates; curr->out != 0; curr++) {
^
drivers/clk/clk-max9485.c:199:9: note: Access to field 'out' results in a dereference of a null pointer (loaded from variable 'prev')
return prev->out;
^~~~
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
2 warnings generated.
>> kernel/bpf/bpf_view.c:151:36: warning: Array subscript is undefined [clang-analyzer-core.uninitialized.ArraySubscript]
target->ctx_arg_info[i].btf_id = bpf_view_btf_ids[idx[i]];
^
kernel/bpf/bpf_view.c:174:2: note: Calling 'register_bpf_view_target'
register_bpf_view_target(&cgroup_view_tinfo, cgroup_view_idx);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/bpf/bpf_view.c:150:14: note: Assuming 'i' is < field 'ctx_arg_info_size'
for (i = 0; i < target->ctx_arg_info_size; ++i)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/bpf/bpf_view.c:150:2: note: Loop condition is true. Entering loop body
for (i = 0; i < target->ctx_arg_info_size; ++i)
^
kernel/bpf/bpf_view.c:150:14: note: Assuming 'i' is < field 'ctx_arg_info_size'
for (i = 0; i < target->ctx_arg_info_size; ++i)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/bpf/bpf_view.c:150:2: note: Loop condition is true. Entering loop body
for (i = 0; i < target->ctx_arg_info_size; ++i)
^
kernel/bpf/bpf_view.c:150:45: note: The value 2 is assigned to 'i'
for (i = 0; i < target->ctx_arg_info_size; ++i)
^~~
kernel/bpf/bpf_view.c:150:14: note: Assuming 'i' is < field 'ctx_arg_info_size'
for (i = 0; i < target->ctx_arg_info_size; ++i)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/bpf/bpf_view.c:150:2: note: Loop condition is true. Entering loop body
for (i = 0; i < target->ctx_arg_info_size; ++i)
^
kernel/bpf/bpf_view.c:151:36: note: Array subscript is undefined
target->ctx_arg_info[i].btf_id = bpf_view_btf_ids[idx[i]];
^ ~~~~~~
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning generated.
Suppressed 1 warnings (1 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
3 warnings generated.
mm/slab.c:1645:2: warning: Assigned value is garbage or undefined [clang-analyzer-core.uninitialized.Assign]
list_for_each_entry_safe(page, n, list, slab_list) {
^
include/linux/list.h:718:7: note: expanded from macro 'list_for_each_entry_safe'
n = list_next_entry(pos, member); \
^
include/linux/list.h:557:2: note: expanded from macro 'list_next_entry'
list_entry((pos)->member.next, typeof(*(pos)), member)
^
include/linux/list.h:513:2: note: expanded from macro 'list_entry'
container_of(ptr, type, member)
^
include/linux/container_of.h:18:2: note: expanded from macro 'container_of'
void *__mptr = (void *)(ptr); \
^
mm/slab.c:4135:6: note: Assuming 'count' is <= MAX_SLABINFO_WRITE
if (count > MAX_SLABINFO_WRITE)
^~~~~~~~~~~~~~~~~~~~~~~~~~
mm/slab.c:4135:2: note: Taking false branch
if (count > MAX_SLABINFO_WRITE)
^
mm/slab.c:4137:2: note: Taking false branch
if (copy_from_user(&kbuf, buffer, count))
^
mm/slab.c:4142:6: note: Assuming 'tmp' is non-null
if (!tmp)
^~~~
mm/slab.c:4142:2: note: Taking false branch
if (!tmp)
^
mm/slab.c:4146:6: note: Assuming the condition is false
if (sscanf(tmp, " %d %d %d", &limit, &batchcount, &shared) != 3)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mm/slab.c:4146:2: note: Taking false branch
if (sscanf(tmp, " %d %d %d", &limit, &batchcount, &shared) != 3)
^
mm/slab.c:4152:2: note: Loop condition is true. Entering loop body
list_for_each_entry(cachep, &slab_caches, list) {
^
include/linux/list.h:630:2: note: expanded from macro 'list_for_each_entry'
for (pos = list_first_entry(head, typeof(*pos), member); \
^
mm/slab.c:4153:7: note: Assuming the condition is true
if (!strcmp(cachep->name, kbuf)) {
^~~~~~~~~~~~~~~~~~~~~~~~~~~
mm/slab.c:4153:3: note: Taking true branch
if (!strcmp(cachep->name, kbuf)) {
^
mm/slab.c:4154:8: note: Assuming 'limit' is >= 1
if (limit < 1 || batchcount < 1 ||
^~~~~~~~~
mm/slab.c:4154:8: note: Left side of '||' is false
mm/slab.c:4154:21: note: Assuming 'batchcount' is >= 1
if (limit < 1 || batchcount < 1 ||
^~~~~~~~~~~~~~
mm/slab.c:4154:8: note: Left side of '||' is false
if (limit < 1 || batchcount < 1 ||
^
mm/slab.c:4155:6: note: Assuming 'batchcount' is <= 'limit'
batchcount > limit || shared < 0) {
^~~~~~~~~~~~~~~~~~
mm/slab.c:4154:8: note: Left side of '||' is false
vim +151 kernel/bpf/bpf_view.c
f3a5b66e45ed0d Hao Luo 2022-01-06 144
f3a5b66e45ed0d Hao Luo 2022-01-06 145 static void register_bpf_view_target(struct bpf_view_target_info *target,
f3a5b66e45ed0d Hao Luo 2022-01-06 146 int idx[BPF_VIEW_CTX_ARG_MAX])
f3a5b66e45ed0d Hao Luo 2022-01-06 147 {
f3a5b66e45ed0d Hao Luo 2022-01-06 148 int i;
f3a5b66e45ed0d Hao Luo 2022-01-06 149
f3a5b66e45ed0d Hao Luo 2022-01-06 150 for (i = 0; i < target->ctx_arg_info_size; ++i)
f3a5b66e45ed0d Hao Luo 2022-01-06 @151 target->ctx_arg_info[i].btf_id = bpf_view_btf_ids[idx[i]];
f3a5b66e45ed0d Hao Luo 2022-01-06 152
f3a5b66e45ed0d Hao Luo 2022-01-06 153 INIT_LIST_HEAD(&target->list);
f3a5b66e45ed0d Hao Luo 2022-01-06 154 list_add(&target->list, &targets);
f3a5b66e45ed0d Hao Luo 2022-01-06 155 }
f3a5b66e45ed0d Hao Luo 2022-01-06 156
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH RFC bpf-next v1 0/8] Pinning bpf objects outside bpffs @ 2022-01-06 21:50 Hao Luo 2022-01-06 21:50 ` [PATCH RFC bpf-next v1 5/8] bpf: Introduce a new program type bpf_view Hao Luo 0 siblings, 1 reply; 3+ messages in thread From: Hao Luo @ 2022-01-06 21:50 UTC (permalink / raw) To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann Cc: Martin KaFai Lau, Song Liu, Yonghong Song, KP Singh, Shakeel Butt, Joe Burton, Stanislav Fomichev, bpf, Hao Luo Bpffs is a pseudo file system that persists bpf objects. Previously bpf objects can only be pinned in bpffs, this patchset extends pinning to allow bpf objects to be pinned (or exposed) to other file systems. In particular, this patchset allows pinning bpf objects in kernfs. This creates a new file entry in the kernfs file system and the created file is able to reference the bpf object. By doing so, bpf can be used to customize the file's operations, such as seq_show. As a concrete usecase of this feature, this patchset introduces a simple new program type called 'bpf_view', which can be used to format a seq file by a kernel object's state. By pinning a bpf_view program into a cgroup directory, userspace is able to read the cgroup's state from file in a format defined by the bpf program. Different from bpffs, kernfs doesn't have a callback when a kernfs node is freed, which is problem if we allow the kernfs node to hold an extra reference of the bpf object, because there is no chance to dec the object's refcnt. Therefore the kernfs node created by pinning doesn't hold reference of the bpf object. The lifetime of the kernfs node depends on the lifetime of the bpf object. Rather than "pinning in kernfs", it is "exposing to kernfs". We require the bpf object to be pinned in bpffs first before it can be pinned in kernfs. When the object is unpinned from bpffs, their kernfs nodes will be removed automatically. This somehow treats a pinned bpf object as a persistent "device". We rely on fsnotify to monitor the inode events in bpffs. A new function bpf_watch_inode() is introduced. It allows registering a callback function at inode destruction. For the kernfs case, a callback that removes kernfs node is registered at the destruction of bpffs inodes. For other file systems such as sockfs, bpf_watch_inode() can monitor the destruction of sockfs inodes and the created file entry can hold the bpf object's reference. In this case, it is truly "pinning". File operations other than seq_show can also be implemented using bpf. For example, bpf may be of help for .poll and .mmap in kernfs. Patch organization: - patch 1/8 and 2/8 are preparations. 1/8 implements bpf_watch_inode(); 2/8 records bpffs inode in bpf object. - patch 3/8 and 4/8 implement generic logic for creating bpf backed kernfs file. - patch 5/8 and 6/8 add a new program type for formatting output. - patch 7/8 implements cgroup seq_show operation using bpf. - patch 8/8 adds selftest. Hao Luo (8): bpf: Support pinning in non-bpf file system. bpf: Record back pointer to the inode in bpffs bpf: Expose bpf object in kernfs bpf: Support removing kernfs entries bpf: Introduce a new program type bpf_view. libbpf: Support of bpf_view prog type. bpf: Add seq_show operation for bpf in cgroupfs selftests/bpf: Test exposing bpf objects in kernfs include/linux/bpf.h | 9 +- include/uapi/linux/bpf.h | 2 + kernel/bpf/Makefile | 2 +- kernel/bpf/bpf_view.c | 190 ++++++++++++++ kernel/bpf/bpf_view.h | 25 ++ kernel/bpf/inode.c | 219 ++++++++++++++-- kernel/bpf/inode.h | 54 ++++ kernel/bpf/kernfs_node.c | 165 ++++++++++++ kernel/bpf/syscall.c | 3 + kernel/bpf/verifier.c | 6 + kernel/trace/bpf_trace.c | 12 +- tools/include/uapi/linux/bpf.h | 2 + tools/lib/bpf/libbpf.c | 21 ++ .../selftests/bpf/prog_tests/pinning_kernfs.c | 245 ++++++++++++++++++ .../selftests/bpf/progs/pinning_kernfs.c | 72 +++++ 15 files changed, 995 insertions(+), 32 deletions(-) create mode 100644 kernel/bpf/bpf_view.c create mode 100644 kernel/bpf/bpf_view.h create mode 100644 kernel/bpf/inode.h create mode 100644 kernel/bpf/kernfs_node.c create mode 100644 tools/testing/selftests/bpf/prog_tests/pinning_kernfs.c create mode 100644 tools/testing/selftests/bpf/progs/pinning_kernfs.c -- 2.34.1.448.ga2b2bfdf31-goog ^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH RFC bpf-next v1 5/8] bpf: Introduce a new program type bpf_view. 2022-01-06 21:50 [PATCH RFC bpf-next v1 0/8] Pinning bpf objects outside bpffs Hao Luo @ 2022-01-06 21:50 ` Hao Luo 2022-01-07 0:35 ` Yonghong Song 0 siblings, 1 reply; 3+ messages in thread From: Hao Luo @ 2022-01-06 21:50 UTC (permalink / raw) To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann Cc: Martin KaFai Lau, Song Liu, Yonghong Song, KP Singh, Shakeel Butt, Joe Burton, Stanislav Fomichev, bpf, Hao Luo Introduce a new program type called "bpf_view", which can be used to print out a kernel object's state to a seq file. So the signature of this program consists of two parameters: a seq file and a kernel object. Currently only 'struct cgroup' is supported. The following patches will introduce a call site for this program type and allow users to customize the format of printing out the state of kernel objects to userspace. Signed-off-by: Hao Luo <haoluo@google.com> --- include/linux/bpf.h | 4 + include/uapi/linux/bpf.h | 2 + kernel/bpf/Makefile | 2 +- kernel/bpf/bpf_view.c | 179 +++++++++++++++++++++++++++++++++ kernel/bpf/bpf_view.h | 24 +++++ kernel/bpf/syscall.c | 3 + kernel/bpf/verifier.c | 6 ++ kernel/trace/bpf_trace.c | 12 ++- tools/include/uapi/linux/bpf.h | 2 + 9 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 kernel/bpf/bpf_view.c create mode 100644 kernel/bpf/bpf_view.h diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 2ec693c3d6f6..16f582dfff7e 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1622,6 +1622,10 @@ void bpf_iter_map_show_fdinfo(const struct bpf_iter_aux_info *aux, int bpf_iter_map_fill_link_info(const struct bpf_iter_aux_info *aux, struct bpf_link_info *info); +bool bpf_view_prog_supported(struct bpf_prog *prog); +int bpf_view_link_attach(const union bpf_attr *attr, bpfptr_t uattr, + struct bpf_prog *prog); + int map_set_for_each_callback_args(struct bpf_verifier_env *env, struct bpf_func_state *caller, struct bpf_func_state *callee); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index b0383d371b9a..efa0f21d13ba 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -982,6 +982,7 @@ enum bpf_attach_type { BPF_MODIFY_RETURN, BPF_LSM_MAC, BPF_TRACE_ITER, + BPF_TRACE_VIEW, BPF_CGROUP_INET4_GETPEERNAME, BPF_CGROUP_INET6_GETPEERNAME, BPF_CGROUP_INET4_GETSOCKNAME, @@ -1009,6 +1010,7 @@ enum bpf_link_type { BPF_LINK_TYPE_NETNS = 5, BPF_LINK_TYPE_XDP = 6, BPF_LINK_TYPE_PERF_EVENT = 7, + BPF_LINK_TYPE_VIEW = 8, MAX_BPF_LINK_TYPE, }; diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index b1abf0d94b5b..c662734d83c5 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -8,7 +8,7 @@ CFLAGS_core.o += $(call cc-disable-warning, override-init) $(cflags-nogcse-yy) obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o prog_iter.o obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o bloom_filter.o -obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o kernfs_node.o +obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o kernfs_node.o bpf_view.o obj-$(CONFIG_BPF_SYSCALL) += bpf_local_storage.o bpf_task_storage.o obj-${CONFIG_BPF_LSM} += bpf_inode_storage.o obj-$(CONFIG_BPF_SYSCALL) += disasm.o diff --git a/kernel/bpf/bpf_view.c b/kernel/bpf/bpf_view.c new file mode 100644 index 000000000000..967a9240bab4 --- /dev/null +++ b/kernel/bpf/bpf_view.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include <linux/bpf.h> +#include <linux/btf_ids.h> +#include <linux/cgroup.h> +#include <linux/filter.h> +#include "bpf_view.h" + +static struct list_head targets = LIST_HEAD_INIT(targets); + +/* bpf_view_link operations */ + +struct bpf_view_target_info { + struct list_head list; + const char *target; + u32 ctx_arg_info_size; + struct bpf_ctx_arg_aux ctx_arg_info[BPF_VIEW_CTX_ARG_MAX]; + u32 btf_id; +}; + +struct bpf_view_link { + struct bpf_link link; + struct bpf_view_target_info *tinfo; +}; + +static void bpf_view_link_release(struct bpf_link *link) +{ +} + +static void bpf_view_link_dealloc(struct bpf_link *link) +{ + struct bpf_view_link *view_link = + container_of(link, struct bpf_view_link, link); + kfree(view_link); +} + +static void bpf_view_link_show_fdinfo(const struct bpf_link *link, + struct seq_file *seq) +{ + struct bpf_view_link *view_link = + container_of(link, struct bpf_view_link, link); + + seq_printf(seq, "attach_target:\t%s\n", view_link->tinfo->target); +} + +static const struct bpf_link_ops bpf_view_link_lops = { + .release = bpf_view_link_release, + .dealloc = bpf_view_link_dealloc, + .show_fdinfo = bpf_view_link_show_fdinfo, +}; + +bool bpf_link_is_view(struct bpf_link *link) +{ + return link->ops == &bpf_view_link_lops; +} + +int bpf_view_link_attach(const union bpf_attr *attr, bpfptr_t uattr, + struct bpf_prog *prog) +{ + struct bpf_link_primer link_primer; + struct bpf_view_target_info *tinfo; + struct bpf_view_link *link; + u32 prog_btf_id; + bool existed = false; + int err; + + prog_btf_id = prog->aux->attach_btf_id; + list_for_each_entry(tinfo, &targets, list) { + if (tinfo->btf_id == prog_btf_id) { + existed = true; + break; + } + } + if (!existed) + return -ENOENT; + + link = kzalloc(sizeof(*link), GFP_USER | __GFP_NOWARN); + if (!link) + return -ENOMEM; + + bpf_link_init(&link->link, BPF_LINK_TYPE_VIEW, &bpf_view_link_lops, prog); + link->tinfo = tinfo; + err = bpf_link_prime(&link->link, &link_primer); + if (err) { + kfree(link); + return err; + } + + return bpf_link_settle(&link_primer); +} + +int run_view_prog(struct bpf_prog *prog, void *ctx) +{ + int ret; + + rcu_read_lock(); + migrate_disable(); + ret = bpf_prog_run(prog, ctx); + migrate_enable(); + rcu_read_unlock(); + + return ret; +} + +bool bpf_view_prog_supported(struct bpf_prog *prog) +{ + const char *attach_fname = prog->aux->attach_func_name; + const char *prefix = BPF_VIEW_FUNC_PREFIX; + u32 prog_btf_id = prog->aux->attach_btf_id; + struct bpf_view_target_info *tinfo; + int prefix_len = strlen(prefix); + bool supported = false; + + if (strncmp(attach_fname, prefix, prefix_len)) + return false; + + list_for_each_entry(tinfo, &targets, list) { + if (tinfo->btf_id && tinfo->btf_id == prog_btf_id) { + supported = true; + break; + } + if (!strcmp(attach_fname + prefix_len, tinfo->target)) { + tinfo->btf_id = prog->aux->attach_btf_id; + supported = true; + break; + } + } + if (supported) { + prog->aux->ctx_arg_info_size = tinfo->ctx_arg_info_size; + prog->aux->ctx_arg_info = tinfo->ctx_arg_info; + } + return supported; +} + +/* Generate BTF_IDs */ +BTF_ID_LIST(bpf_view_btf_ids) +BTF_ID(struct, seq_file) +BTF_ID(struct, cgroup) + +/* Index of bpf_view_btf_ids */ +enum { + BTF_ID_SEQ_FILE = 0, + BTF_ID_CGROUP, +}; + +static void register_bpf_view_target(struct bpf_view_target_info *target, + int idx[BPF_VIEW_CTX_ARG_MAX]) +{ + int i; + + for (i = 0; i < target->ctx_arg_info_size; ++i) + target->ctx_arg_info[i].btf_id = bpf_view_btf_ids[idx[i]]; + + INIT_LIST_HEAD(&target->list); + list_add(&target->list, &targets); +} + +DEFINE_BPF_VIEW_FUNC(cgroup, struct seq_file *seq, struct cgroup *cgroup) + +static struct bpf_view_target_info cgroup_view_tinfo = { + .target = "cgroup", + .ctx_arg_info_size = 2, + .ctx_arg_info = { + { offsetof(struct bpf_view_cgroup_ctx, seq), PTR_TO_BTF_ID }, + { offsetof(struct bpf_view_cgroup_ctx, cgroup), PTR_TO_BTF_ID }, + }, + .btf_id = 0, +}; + +static int __init bpf_view_init(void) +{ + int cgroup_view_idx[BPF_VIEW_CTX_ARG_MAX] = { + BTF_ID_SEQ_FILE, BTF_ID_CGROUP }; + + register_bpf_view_target(&cgroup_view_tinfo, cgroup_view_idx); + + return 0; +} +late_initcall(bpf_view_init); + diff --git a/kernel/bpf/bpf_view.h b/kernel/bpf/bpf_view.h new file mode 100644 index 000000000000..1a1110a5727f --- /dev/null +++ b/kernel/bpf/bpf_view.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0-only +#ifndef _BPF_VIEW_H_ +#define _BPF_VIEW_H_ + +#include <linux/bpf.h> + +#define BPF_VIEW_FUNC_PREFIX "bpf_view_" +#define DEFINE_BPF_VIEW_FUNC(target, args...) \ + extern int bpf_view_ ## target(args); \ + int __init bpf_view_ ## target(args) { return 0; } + +#define BPF_VIEW_CTX_ARG_MAX 2 + +struct bpf_view_cgroup_ctx { + __bpf_md_ptr(struct seq_file *, seq); + __bpf_md_ptr(struct cgroup *, cgroup); +}; + +bool bpf_link_is_view(struct bpf_link *link); + +/* Run a bpf_view program */ +int run_view_prog(struct bpf_prog *prog, void *ctx); + +#endif // _BPF_VIEW_H_ diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index fa4505f9b611..32ac84d3ac0b 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -3175,6 +3175,7 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type) case BPF_CGROUP_SETSOCKOPT: return BPF_PROG_TYPE_CGROUP_SOCKOPT; case BPF_TRACE_ITER: + case BPF_TRACE_VIEW: return BPF_PROG_TYPE_TRACING; case BPF_SK_LOOKUP: return BPF_PROG_TYPE_SK_LOOKUP; @@ -4235,6 +4236,8 @@ static int tracing_bpf_link_attach(const union bpf_attr *attr, bpfptr_t uattr, if (prog->expected_attach_type == BPF_TRACE_ITER) return bpf_iter_link_attach(attr, uattr, prog); + else if (prog->expected_attach_type == BPF_TRACE_VIEW) + return bpf_view_link_attach(attr, uattr, prog); else if (prog->type == BPF_PROG_TYPE_EXT) return bpf_tracing_prog_attach(prog, attr->link_create.target_fd, diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index bfb45381fb3f..ce7816519c93 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -9770,6 +9770,7 @@ static int check_return_code(struct bpf_verifier_env *env) case BPF_MODIFY_RETURN: return 0; case BPF_TRACE_ITER: + case BPF_TRACE_VIEW: break; default: return -ENOTSUPP; @@ -13971,6 +13972,7 @@ int bpf_check_attach_target(struct bpf_verifier_log *log, break; case BPF_TRACE_ITER: + case BPF_TRACE_VIEW: if (!btf_type_is_func(t)) { bpf_log(log, "attach_btf_id %u is not a function\n", btf_id); @@ -14147,6 +14149,10 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) if (!bpf_iter_prog_supported(prog)) return -EINVAL; return 0; + } else if (prog->expected_attach_type == BPF_TRACE_VIEW) { + if (!bpf_view_prog_supported(prog)) + return -EINVAL; + return 0; } if (prog->type == BPF_PROG_TYPE_LSM) { diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 21aa30644219..9413b5af6e2c 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1630,6 +1630,12 @@ raw_tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) } } +static inline bool prog_support_seq_helpers(const struct bpf_prog *prog) +{ + return prog->expected_attach_type == BPF_TRACE_ITER || + prog->expected_attach_type == BPF_TRACE_VIEW; +} + const struct bpf_func_proto * tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) { @@ -1663,15 +1669,15 @@ tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_get_socket_ptr_cookie_proto; #endif case BPF_FUNC_seq_printf: - return prog->expected_attach_type == BPF_TRACE_ITER ? + return prog_support_seq_helpers(prog) ? &bpf_seq_printf_proto : NULL; case BPF_FUNC_seq_write: - return prog->expected_attach_type == BPF_TRACE_ITER ? + return prog_support_seq_helpers(prog) ? &bpf_seq_write_proto : NULL; case BPF_FUNC_seq_printf_btf: - return prog->expected_attach_type == BPF_TRACE_ITER ? + return prog_support_seq_helpers(prog) ? &bpf_seq_printf_btf_proto : NULL; case BPF_FUNC_d_path: diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index b0383d371b9a..efa0f21d13ba 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -982,6 +982,7 @@ enum bpf_attach_type { BPF_MODIFY_RETURN, BPF_LSM_MAC, BPF_TRACE_ITER, + BPF_TRACE_VIEW, BPF_CGROUP_INET4_GETPEERNAME, BPF_CGROUP_INET6_GETPEERNAME, BPF_CGROUP_INET4_GETSOCKNAME, @@ -1009,6 +1010,7 @@ enum bpf_link_type { BPF_LINK_TYPE_NETNS = 5, BPF_LINK_TYPE_XDP = 6, BPF_LINK_TYPE_PERF_EVENT = 7, + BPF_LINK_TYPE_VIEW = 8, MAX_BPF_LINK_TYPE, }; -- 2.34.1.448.ga2b2bfdf31-goog ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH RFC bpf-next v1 5/8] bpf: Introduce a new program type bpf_view. 2022-01-06 21:50 ` [PATCH RFC bpf-next v1 5/8] bpf: Introduce a new program type bpf_view Hao Luo @ 2022-01-07 0:35 ` Yonghong Song 0 siblings, 0 replies; 3+ messages in thread From: Yonghong Song @ 2022-01-07 0:35 UTC (permalink / raw) To: Hao Luo, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann Cc: Martin KaFai Lau, Song Liu, KP Singh, Shakeel Butt, Joe Burton, Stanislav Fomichev, bpf On 1/6/22 1:50 PM, Hao Luo wrote: > Introduce a new program type called "bpf_view", which can be used to > print out a kernel object's state to a seq file. So the signature of > this program consists of two parameters: a seq file and a kernel object. > Currently only 'struct cgroup' is supported. > > The following patches will introduce a call site for this program type > and allow users to customize the format of printing out the state of > kernel objects to userspace. > > Signed-off-by: Hao Luo <haoluo@google.com> > --- > include/linux/bpf.h | 4 + > include/uapi/linux/bpf.h | 2 + > kernel/bpf/Makefile | 2 +- > kernel/bpf/bpf_view.c | 179 +++++++++++++++++++++++++++++++++ > kernel/bpf/bpf_view.h | 24 +++++ > kernel/bpf/syscall.c | 3 + > kernel/bpf/verifier.c | 6 ++ > kernel/trace/bpf_trace.c | 12 ++- > tools/include/uapi/linux/bpf.h | 2 + > 9 files changed, 230 insertions(+), 4 deletions(-) > create mode 100644 kernel/bpf/bpf_view.c > create mode 100644 kernel/bpf/bpf_view.h > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index 2ec693c3d6f6..16f582dfff7e 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -1622,6 +1622,10 @@ void bpf_iter_map_show_fdinfo(const struct bpf_iter_aux_info *aux, > int bpf_iter_map_fill_link_info(const struct bpf_iter_aux_info *aux, > struct bpf_link_info *info); > > +bool bpf_view_prog_supported(struct bpf_prog *prog); > +int bpf_view_link_attach(const union bpf_attr *attr, bpfptr_t uattr, > + struct bpf_prog *prog); > + > int map_set_for_each_callback_args(struct bpf_verifier_env *env, > struct bpf_func_state *caller, > struct bpf_func_state *callee); > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h > index b0383d371b9a..efa0f21d13ba 100644 > --- a/include/uapi/linux/bpf.h > +++ b/include/uapi/linux/bpf.h > @@ -982,6 +982,7 @@ enum bpf_attach_type { > BPF_MODIFY_RETURN, > BPF_LSM_MAC, > BPF_TRACE_ITER, > + BPF_TRACE_VIEW, Please add the new entry to the end of enum list. Otherwise, this will break backward compatibility. > BPF_CGROUP_INET4_GETPEERNAME, > BPF_CGROUP_INET6_GETPEERNAME, > BPF_CGROUP_INET4_GETSOCKNAME, > @@ -1009,6 +1010,7 @@ enum bpf_link_type { > BPF_LINK_TYPE_NETNS = 5, > BPF_LINK_TYPE_XDP = 6, > BPF_LINK_TYPE_PERF_EVENT = 7, > + BPF_LINK_TYPE_VIEW = 8, > > MAX_BPF_LINK_TYPE, > }; [...] ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-01-10 7:06 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-01-10 7:06 [PATCH RFC bpf-next v1 5/8] bpf: Introduce a new program type bpf_view kernel test robot -- strict thread matches above, loose matches on Subject: below -- 2022-01-06 21:50 [PATCH RFC bpf-next v1 0/8] Pinning bpf objects outside bpffs Hao Luo 2022-01-06 21:50 ` [PATCH RFC bpf-next v1 5/8] bpf: Introduce a new program type bpf_view Hao Luo 2022-01-07 0:35 ` Yonghong Song
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.