diff options
author | TCWG BuildSlave <tcwg-buildslave@linaro.org> | 2022-12-17 10:42:08 +0000 |
---|---|---|
committer | TCWG BuildSlave <tcwg-buildslave@linaro.org> | 2022-12-17 10:42:08 +0000 |
commit | a37300bc42b8909c5a23175b14624145d0477eb9 (patch) | |
tree | c768951350da1ec5251ff431acbe475794591699 /jenkins | |
parent | 495f358cce983df3da34703dfa99addba5dd57f7 (diff) |
39: onsuccess: #533: 21611: Success after linux: 11895 commits
BUILD_URL: https://ci.linaro.org/job/tcwg_kernel-llvm-build-llvm-master-aarch64-mainline-allyesconfig/533/
Success after linux: 11895 commits:
Results changed to
-10
# build_abe binutils:
-9
# build_kernel_llvm:
-5
# build_abe qemu:
-2
# linux_n_obj:
21611
from
-10
# build_abe binutils:
-9
# build_kernel_llvm:
-5
# build_abe qemu:
-2
# linux_n_obj:
21442
# First few build errors in logs:
# 00:29:50 kernel/bpf/verifier.c:8340:19: error: array index 5 is past the end of the array (that has type 'u32[5]' (aka 'unsigned int[5]')) [-Werror,-Warray-bounds]
# 00:29:50 kernel/bpf/verifier.c:8819:24: error: array index 5 is past the end of the array (that has type 'u32[5]' (aka 'unsigned int[5]')) [-Werror,-Warray-bounds]
# 00:29:50 make[3]: *** [scripts/Makefile.build:250: kernel/bpf/verifier.o] Error 1
# 00:31:38 make[2]: *** [scripts/Makefile.build:500: kernel/bpf] Error 2
# 00:38:27 make[1]: *** [scripts/Makefile.build:500: kernel] Error 2
# 01:20:17 make: *** [Makefile:1992: .] Error 2
Diffstat (limited to 'jenkins')
-rw-r--r-- | jenkins/jira-status.draft | 4 | ||||
-rw-r--r-- | jenkins/mail-body.draft | 609 | ||||
-rw-r--r-- | jenkins/mail-recipients.draft | 1 | ||||
-rw-r--r-- | jenkins/mail-subject.draft | 1 | ||||
-rwxr-xr-x | jenkins/notify.sh | 3 |
5 files changed, 0 insertions, 618 deletions
diff --git a/jenkins/jira-status.draft b/jenkins/jira-status.draft deleted file mode 100644 index 6281960..0000000 --- a/jenkins/jira-status.draft +++ /dev/null @@ -1,4 +0,0 @@ -[LLVM-647] -#INTERESTING_COMMIT_STATUS# - -Details: https://ci.linaro.org/job/tcwg_kernel-llvm-build-llvm-master-aarch64-mainline-allyesconfig/532/artifact/artifacts/jenkins/mail-body.txt/*view*/ diff --git a/jenkins/mail-body.draft b/jenkins/mail-body.draft deleted file mode 100644 index 0053022..0000000 --- a/jenkins/mail-body.draft +++ /dev/null @@ -1,609 +0,0 @@ -Failure after v6.1-rc4-1107-g8cab76ec6349: bpf: Introduce single ownership BPF linked list API: - -Results changed to --10 -# build_abe binutils: --9 -# build_kernel_llvm: --5 -# build_abe qemu: --2 -# linux_n_obj: -21442 -# First few build errors in logs: -# 00:29:50 kernel/bpf/verifier.c:8340:19: error: array index 5 is past the end of the array (that has type 'u32[5]' (aka 'unsigned int[5]')) [-Werror,-Warray-bounds] -# 00:29:50 kernel/bpf/verifier.c:8819:24: error: array index 5 is past the end of the array (that has type 'u32[5]' (aka 'unsigned int[5]')) [-Werror,-Warray-bounds] -# 00:29:50 make[3]: *** [scripts/Makefile.build:250: kernel/bpf/verifier.o] Error 1 -# 00:31:38 make[2]: *** [scripts/Makefile.build:500: kernel/bpf] Error 2 -# 00:38:27 make[1]: *** [scripts/Makefile.build:500: kernel] Error 2 -# 01:20:17 make: *** [Makefile:1992: .] Error 2 - -from --10 -# build_abe binutils: --9 -# build_kernel_llvm: --5 -# build_abe qemu: --2 -# linux_n_obj: -21521 -# linux build successful: -all - -THIS IS THE END OF INTERESTING STUFF. BELOW ARE LINKS TO BUILDS, REPRODUCTION INSTRUCTIONS, AND THE RAW COMMIT. - -For latest status see comments in https://linaro.atlassian.net/browse/LLVM-647 . -#INTERESTING_COMMIT_STATUS# - -Bad build: https://ci.linaro.org/job/tcwg_kernel-llvm-build-llvm-master-aarch64-mainline-allyesconfig/532/artifact/artifacts -Good build: https://ci.linaro.org/job/tcwg_kernel-llvm-build-llvm-master-aarch64-mainline-allyesconfig/531/artifact/artifacts - -Reproduce current build: -<cut> -mkdir -p investigate-linux-8cab76ec634995e59a8b6346bf8b835ab7fad3a3 -cd investigate-linux-8cab76ec634995e59a8b6346bf8b835ab7fad3a3 - -# Fetch scripts -git clone https://git.linaro.org/toolchain/jenkins-scripts - -# Fetch manifests for bad and good builds -mkdir -p bad/artifacts good/artifacts -curl -o bad/artifacts/manifest.sh https://ci.linaro.org/job/tcwg_kernel-llvm-build-llvm-master-aarch64-mainline-allyesconfig/532/artifact/artifacts/manifest.sh --fail -curl -o good/artifacts/manifest.sh https://ci.linaro.org/job/tcwg_kernel-llvm-build-llvm-master-aarch64-mainline-allyesconfig/531/artifact/artifacts/manifest.sh --fail - -# Reproduce bad build -(cd bad; ../jenkins-scripts/tcwg_kernel-build.sh ^^ true %%rr[top_artifacts] artifacts) -# Reproduce good build -(cd good; ../jenkins-scripts/tcwg_kernel-build.sh ^^ true %%rr[top_artifacts] artifacts) -</cut> - -Full commit (up to 1000 lines): -<cut> -commit 8cab76ec634995e59a8b6346bf8b835ab7fad3a3 -Author: Kumar Kartikeya Dwivedi <memxor@gmail.com> -Date: Fri Nov 18 07:26:06 2022 +0530 - - bpf: Introduce single ownership BPF linked list API - - Add a linked list API for use in BPF programs, where it expects - protection from the bpf_spin_lock in the same allocation as the - bpf_list_head. For now, only one bpf_spin_lock can be present hence that - is assumed to be the one protecting the bpf_list_head. - - The following functions are added to kick things off: - - // Add node to beginning of list - void bpf_list_push_front(struct bpf_list_head *head, struct bpf_list_node *node); - - // Add node to end of list - void bpf_list_push_back(struct bpf_list_head *head, struct bpf_list_node *node); - - // Remove node at beginning of list and return it - struct bpf_list_node *bpf_list_pop_front(struct bpf_list_head *head); - - // Remove node at end of list and return it - struct bpf_list_node *bpf_list_pop_back(struct bpf_list_head *head); - - The lock protecting the bpf_list_head needs to be taken for all - operations. The verifier ensures that the lock that needs to be taken is - always held, and only the correct lock is taken for these operations. - These checks are made statically by relying on the reg->id preserved for - registers pointing into regions having both bpf_spin_lock and the - objects protected by it. The comment over check_reg_allocation_locked in - this change describes the logic in detail. - - Note that bpf_list_push_front and bpf_list_push_back are meant to - consume the object containing the node in the 1st argument, however that - specific mechanism is intended to not release the ref_obj_id directly - until the bpf_spin_unlock is called. In this commit, nothing is done, - but the next commit will be introducing logic to handle this case, so it - has been left as is for now. - - bpf_list_pop_front and bpf_list_pop_back delete the first or last item - of the list respectively, and return pointer to the element at the - list_node offset. The user can then use container_of style macro to get - the actual entry type. The verifier however statically knows the actual - type, so the safety properties are still preserved. - - With these additions, programs can now manage their own linked lists and - store their objects in them. - - Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> - Link: https://lore.kernel.org/r/20221118015614.2013203-17-memxor@gmail.com - Signed-off-by: Alexei Starovoitov <ast@kernel.org> ---- - kernel/bpf/helpers.c | 55 ++++- - kernel/bpf/verifier.c | 275 ++++++++++++++++++++++++- - tools/testing/selftests/bpf/bpf_experimental.h | 28 +++ - 3 files changed, 349 insertions(+), 9 deletions(-) - -diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c -index 71d803ca0c1d..212e791d7452 100644 ---- a/kernel/bpf/helpers.c -+++ b/kernel/bpf/helpers.c -@@ -1780,6 +1780,50 @@ void bpf_obj_drop_impl(void *p__alloc, void *meta__ign) - bpf_mem_free(&bpf_global_ma, p); - } - -+static void __bpf_list_add(struct bpf_list_node *node, struct bpf_list_head *head, bool tail) -+{ -+ struct list_head *n = (void *)node, *h = (void *)head; -+ -+ if (unlikely(!h->next)) -+ INIT_LIST_HEAD(h); -+ if (unlikely(!n->next)) -+ INIT_LIST_HEAD(n); -+ tail ? list_add_tail(n, h) : list_add(n, h); -+} -+ -+void bpf_list_push_front(struct bpf_list_head *head, struct bpf_list_node *node) -+{ -+ return __bpf_list_add(node, head, false); -+} -+ -+void bpf_list_push_back(struct bpf_list_head *head, struct bpf_list_node *node) -+{ -+ return __bpf_list_add(node, head, true); -+} -+ -+static struct bpf_list_node *__bpf_list_del(struct bpf_list_head *head, bool tail) -+{ -+ struct list_head *n, *h = (void *)head; -+ -+ if (unlikely(!h->next)) -+ INIT_LIST_HEAD(h); -+ if (list_empty(h)) -+ return NULL; -+ n = tail ? h->prev : h->next; -+ list_del_init(n); -+ return (struct bpf_list_node *)n; -+} -+ -+struct bpf_list_node *bpf_list_pop_front(struct bpf_list_head *head) -+{ -+ return __bpf_list_del(head, false); -+} -+ -+struct bpf_list_node *bpf_list_pop_back(struct bpf_list_head *head) -+{ -+ return __bpf_list_del(head, true); -+} -+ - __diag_pop(); - - BTF_SET8_START(generic_btf_ids) -@@ -1788,6 +1832,10 @@ BTF_ID_FLAGS(func, crash_kexec, KF_DESTRUCTIVE) - #endif - BTF_ID_FLAGS(func, bpf_obj_new_impl, KF_ACQUIRE | KF_RET_NULL) - BTF_ID_FLAGS(func, bpf_obj_drop_impl, KF_RELEASE) -+BTF_ID_FLAGS(func, bpf_list_push_front) -+BTF_ID_FLAGS(func, bpf_list_push_back) -+BTF_ID_FLAGS(func, bpf_list_pop_front, KF_ACQUIRE | KF_RET_NULL) -+BTF_ID_FLAGS(func, bpf_list_pop_back, KF_ACQUIRE | KF_RET_NULL) - BTF_SET8_END(generic_btf_ids) - - static const struct btf_kfunc_id_set generic_kfunc_set = { -@@ -1797,7 +1845,12 @@ static const struct btf_kfunc_id_set generic_kfunc_set = { - - static int __init kfunc_init(void) - { -- return register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &generic_kfunc_set); -+ int ret; -+ -+ ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &generic_kfunc_set); -+ if (ret) -+ return ret; -+ return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, &generic_kfunc_set); - } - - late_initcall(kfunc_init); -diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c -index a339a39d895c..1364df74129e 100644 ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -7883,6 +7883,9 @@ struct bpf_kfunc_call_arg_meta { - struct btf *btf; - u32 btf_id; - } arg_obj_drop; -+ struct { -+ struct btf_field *field; -+ } arg_list_head; - }; - - static bool is_kfunc_acquire(struct bpf_kfunc_call_arg_meta *meta) -@@ -7987,13 +7990,17 @@ static bool is_kfunc_arg_scalar_with_name(const struct btf *btf, - - enum { - KF_ARG_DYNPTR_ID, -+ KF_ARG_LIST_HEAD_ID, -+ KF_ARG_LIST_NODE_ID, - }; - - BTF_ID_LIST(kf_arg_btf_ids) - BTF_ID(struct, bpf_dynptr_kern) -+BTF_ID(struct, bpf_list_head) -+BTF_ID(struct, bpf_list_node) - --static bool is_kfunc_arg_dynptr(const struct btf *btf, -- const struct btf_param *arg) -+static bool __is_kfunc_ptr_arg_type(const struct btf *btf, -+ const struct btf_param *arg, int type) - { - const struct btf_type *t; - u32 res_id; -@@ -8006,7 +8013,22 @@ static bool is_kfunc_arg_dynptr(const struct btf *btf, - t = btf_type_skip_modifiers(btf, t->type, &res_id); - if (!t) - return false; -- return btf_types_are_same(btf, res_id, btf_vmlinux, kf_arg_btf_ids[KF_ARG_DYNPTR_ID]); -+ return btf_types_are_same(btf, res_id, btf_vmlinux, kf_arg_btf_ids[type]); -+} -+ -+static bool is_kfunc_arg_dynptr(const struct btf *btf, const struct btf_param *arg) -+{ -+ return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_DYNPTR_ID); -+} -+ -+static bool is_kfunc_arg_list_head(const struct btf *btf, const struct btf_param *arg) -+{ -+ return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_LIST_HEAD_ID); -+} -+ -+static bool is_kfunc_arg_list_node(const struct btf *btf, const struct btf_param *arg) -+{ -+ return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_LIST_NODE_ID); - } - - /* Returns true if struct is composed of scalars, 4 levels of nesting allowed */ -@@ -8063,6 +8085,8 @@ enum kfunc_ptr_arg_type { - KF_ARG_PTR_TO_ALLOC_BTF_ID, /* Allocated object */ - KF_ARG_PTR_TO_KPTR, /* PTR_TO_KPTR but type specific */ - KF_ARG_PTR_TO_DYNPTR, -+ KF_ARG_PTR_TO_LIST_HEAD, -+ KF_ARG_PTR_TO_LIST_NODE, - KF_ARG_PTR_TO_BTF_ID, /* Also covers reg2btf_ids conversions */ - KF_ARG_PTR_TO_MEM, - KF_ARG_PTR_TO_MEM_SIZE, /* Size derived from next argument, skip it */ -@@ -8071,16 +8095,28 @@ enum kfunc_ptr_arg_type { - enum special_kfunc_type { - KF_bpf_obj_new_impl, - KF_bpf_obj_drop_impl, -+ KF_bpf_list_push_front, -+ KF_bpf_list_push_back, -+ KF_bpf_list_pop_front, -+ KF_bpf_list_pop_back, - }; - - BTF_SET_START(special_kfunc_set) - BTF_ID(func, bpf_obj_new_impl) - BTF_ID(func, bpf_obj_drop_impl) -+BTF_ID(func, bpf_list_push_front) -+BTF_ID(func, bpf_list_push_back) -+BTF_ID(func, bpf_list_pop_front) -+BTF_ID(func, bpf_list_pop_back) - BTF_SET_END(special_kfunc_set) - - BTF_ID_LIST(special_kfunc_list) - BTF_ID(func, bpf_obj_new_impl) - BTF_ID(func, bpf_obj_drop_impl) -+BTF_ID(func, bpf_list_push_front) -+BTF_ID(func, bpf_list_push_back) -+BTF_ID(func, bpf_list_pop_front) -+BTF_ID(func, bpf_list_pop_back) - - static enum kfunc_ptr_arg_type - get_kfunc_ptr_arg_type(struct bpf_verifier_env *env, -@@ -8123,6 +8159,12 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env, - if (is_kfunc_arg_dynptr(meta->btf, &args[argno])) - return KF_ARG_PTR_TO_DYNPTR; - -+ if (is_kfunc_arg_list_head(meta->btf, &args[argno])) -+ return KF_ARG_PTR_TO_LIST_HEAD; -+ -+ if (is_kfunc_arg_list_node(meta->btf, &args[argno])) -+ return KF_ARG_PTR_TO_LIST_NODE; -+ - if ((base_type(reg->type) == PTR_TO_BTF_ID || reg2btf_ids[base_type(reg->type)])) { - if (!btf_type_is_struct(ref_t)) { - verbose(env, "kernel function %s args#%d pointer type %s %s is not supported\n", -@@ -8218,6 +8260,182 @@ static int process_kf_arg_ptr_to_kptr(struct bpf_verifier_env *env, - return 0; - } - -+/* Implementation details: -+ * -+ * Each register points to some region of memory, which we define as an -+ * allocation. Each allocation may embed a bpf_spin_lock which protects any -+ * special BPF objects (bpf_list_head, bpf_rb_root, etc.) part of the same -+ * allocation. The lock and the data it protects are colocated in the same -+ * memory region. -+ * -+ * Hence, everytime a register holds a pointer value pointing to such -+ * allocation, the verifier preserves a unique reg->id for it. -+ * -+ * The verifier remembers the lock 'ptr' and the lock 'id' whenever -+ * bpf_spin_lock is called. -+ * -+ * To enable this, lock state in the verifier captures two values: -+ * active_lock.ptr = Register's type specific pointer -+ * active_lock.id = A unique ID for each register pointer value -+ * -+ * Currently, PTR_TO_MAP_VALUE and PTR_TO_BTF_ID | MEM_ALLOC are the two -+ * supported register types. -+ * -+ * The active_lock.ptr in case of map values is the reg->map_ptr, and in case of -+ * allocated objects is the reg->btf pointer. -+ * -+ * The active_lock.id is non-unique for maps supporting direct_value_addr, as we -+ * can establish the provenance of the map value statically for each distinct -+ * lookup into such maps. They always contain a single map value hence unique -+ * IDs for each pseudo load pessimizes the algorithm and rejects valid programs. -+ * -+ * So, in case of global variables, they use array maps with max_entries = 1, -+ * hence their active_lock.ptr becomes map_ptr and id = 0 (since they all point -+ * into the same map value as max_entries is 1, as described above). -+ * -+ * In case of inner map lookups, the inner map pointer has same map_ptr as the -+ * outer map pointer (in verifier context), but each lookup into an inner map -+ * assigns a fresh reg->id to the lookup, so while lookups into distinct inner -+ * maps from the same outer map share the same map_ptr as active_lock.ptr, they -+ * will get different reg->id assigned to each lookup, hence different -+ * active_lock.id. -+ * -+ * In case of allocated objects, active_lock.ptr is the reg->btf, and the -+ * reg->id is a unique ID preserved after the NULL pointer check on the pointer -+ * returned from bpf_obj_new. Each allocation receives a new reg->id. -+ */ -+static int check_reg_allocation_locked(struct bpf_verifier_env *env, struct bpf_reg_state *reg) -+{ -+ void *ptr; -+ u32 id; -+ -+ switch ((int)reg->type) { -+ case PTR_TO_MAP_VALUE: -+ ptr = reg->map_ptr; -+ break; -+ case PTR_TO_BTF_ID | MEM_ALLOC: -+ ptr = reg->btf; -+ break; -+ default: -+ verbose(env, "verifier internal error: unknown reg type for lock check\n"); -+ return -EFAULT; -+ } -+ id = reg->id; -+ -+ if (!env->cur_state->active_lock.ptr) -+ return -EINVAL; -+ if (env->cur_state->active_lock.ptr != ptr || -+ env->cur_state->active_lock.id != id) { -+ verbose(env, "held lock and object are not in the same allocation\n"); -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static bool is_bpf_list_api_kfunc(u32 btf_id) -+{ -+ return btf_id == special_kfunc_list[KF_bpf_list_push_front] || -+ btf_id == special_kfunc_list[KF_bpf_list_push_back] || -+ btf_id == special_kfunc_list[KF_bpf_list_pop_front] || -+ btf_id == special_kfunc_list[KF_bpf_list_pop_back]; -+} -+ -+static int process_kf_arg_ptr_to_list_head(struct bpf_verifier_env *env, -+ struct bpf_reg_state *reg, u32 regno, -+ struct bpf_kfunc_call_arg_meta *meta) -+{ -+ struct btf_field *field; -+ struct btf_record *rec; -+ u32 list_head_off; -+ -+ if (meta->btf != btf_vmlinux || !is_bpf_list_api_kfunc(meta->func_id)) { -+ verbose(env, "verifier internal error: bpf_list_head argument for unknown kfunc\n"); -+ return -EFAULT; -+ } -+ -+ if (!tnum_is_const(reg->var_off)) { -+ verbose(env, -+ "R%d doesn't have constant offset. bpf_list_head has to be at the constant offset\n", -+ regno); -+ return -EINVAL; -+ } -+ -+ rec = reg_btf_record(reg); -+ list_head_off = reg->off + reg->var_off.value; -+ field = btf_record_find(rec, list_head_off, BPF_LIST_HEAD); -+ if (!field) { -+ verbose(env, "bpf_list_head not found at offset=%u\n", list_head_off); -+ return -EINVAL; -+ } -+ -+ /* All functions require bpf_list_head to be protected using a bpf_spin_lock */ -+ if (check_reg_allocation_locked(env, reg)) { -+ verbose(env, "bpf_spin_lock at off=%d must be held for bpf_list_head\n", -+ rec->spin_lock_off); -+ return -EINVAL; -+ } -+ -+ if (meta->arg_list_head.field) { -+ verbose(env, "verifier internal error: repeating bpf_list_head arg\n"); -+ return -EFAULT; -+ } -+ meta->arg_list_head.field = field; -+ return 0; -+} -+ -+static int process_kf_arg_ptr_to_list_node(struct bpf_verifier_env *env, -+ struct bpf_reg_state *reg, u32 regno, -+ struct bpf_kfunc_call_arg_meta *meta) -+{ -+ const struct btf_type *et, *t; -+ struct btf_field *field; -+ struct btf_record *rec; -+ u32 list_node_off; -+ -+ if (meta->btf != btf_vmlinux || -+ (meta->func_id != special_kfunc_list[KF_bpf_list_push_front] && -+ meta->func_id != special_kfunc_list[KF_bpf_list_push_back])) { -+ verbose(env, "verifier internal error: bpf_list_node argument for unknown kfunc\n"); -+ return -EFAULT; -+ } -+ -+ if (!tnum_is_const(reg->var_off)) { -+ verbose(env, -+ "R%d doesn't have constant offset. bpf_list_node has to be at the constant offset\n", -+ regno); -+ return -EINVAL; -+ } -+ -+ rec = reg_btf_record(reg); -+ list_node_off = reg->off + reg->var_off.value; -+ field = btf_record_find(rec, list_node_off, BPF_LIST_NODE); -+ if (!field || field->offset != list_node_off) { -+ verbose(env, "bpf_list_node not found at offset=%u\n", list_node_off); -+ return -EINVAL; -+ } -+ -+ field = meta->arg_list_head.field; -+ -+ et = btf_type_by_id(field->list_head.btf, field->list_head.value_btf_id); -+ t = btf_type_by_id(reg->btf, reg->btf_id); -+ if (!btf_struct_ids_match(&env->log, reg->btf, reg->btf_id, 0, field->list_head.btf, -+ field->list_head.value_btf_id, true)) { -+ verbose(env, "operation on bpf_list_head expects arg#1 bpf_list_node at offset=%d " -+ "in struct %s, but arg is at offset=%d in struct %s\n", -+ field->list_head.node_offset, btf_name_by_offset(field->list_head.btf, et->name_off), -+ list_node_off, btf_name_by_offset(reg->btf, t->name_off)); -+ return -EINVAL; -+ } -+ -+ if (list_node_off != field->list_head.node_offset) { -+ verbose(env, "arg#1 offset=%d, but expected bpf_list_node at offset=%d in struct %s\n", -+ list_node_off, field->list_head.node_offset, -+ btf_name_by_offset(field->list_head.btf, et->name_off)); -+ return -EINVAL; -+ } -+ return 0; -+} -+ - static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_arg_meta *meta) - { - const char *func_name = meta->func_name, *ref_tname; -@@ -8336,6 +8554,8 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ - break; - case KF_ARG_PTR_TO_KPTR: - case KF_ARG_PTR_TO_DYNPTR: -+ case KF_ARG_PTR_TO_LIST_HEAD: -+ case KF_ARG_PTR_TO_LIST_NODE: - case KF_ARG_PTR_TO_MEM: - case KF_ARG_PTR_TO_MEM_SIZE: - /* Trusted by default */ -@@ -8400,6 +8620,33 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ - return -EINVAL; - } - break; -+ case KF_ARG_PTR_TO_LIST_HEAD: -+ if (reg->type != PTR_TO_MAP_VALUE && -+ reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) { -+ verbose(env, "arg#%d expected pointer to map value or allocated object\n", i); -+ return -EINVAL; -+ } -+ if (reg->type == (PTR_TO_BTF_ID | MEM_ALLOC) && !reg->ref_obj_id) { -+ verbose(env, "allocated object must be referenced\n"); -+ return -EINVAL; -+ } -+ ret = process_kf_arg_ptr_to_list_head(env, reg, regno, meta); -+ if (ret < 0) -+ return ret; -+ break; -+ case KF_ARG_PTR_TO_LIST_NODE: -+ if (reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) { -+ verbose(env, "arg#%d expected pointer to allocated object\n", i); -+ return -EINVAL; -+ } -+ if (!reg->ref_obj_id) { -+ verbose(env, "allocated object must be referenced\n"); -+ return -EINVAL; -+ } -+ ret = process_kf_arg_ptr_to_list_node(env, reg, regno, meta); -+ if (ret < 0) -+ return ret; -+ break; - case KF_ARG_PTR_TO_BTF_ID: - /* Only base_type is checked, further checks are done here */ - if (reg->type != PTR_TO_BTF_ID && -@@ -8568,6 +8815,15 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn, - env->insn_aux_data[insn_idx].kptr_struct_meta = - btf_find_struct_meta(meta.arg_obj_drop.btf, - meta.arg_obj_drop.btf_id); -+ } else if (meta.func_id == special_kfunc_list[KF_bpf_list_pop_front] || -+ meta.func_id == special_kfunc_list[KF_bpf_list_pop_back]) { -+ struct btf_field *field = meta.arg_list_head.field; -+ -+ mark_reg_known_zero(env, regs, BPF_REG_0); -+ regs[BPF_REG_0].type = PTR_TO_BTF_ID | MEM_ALLOC; -+ regs[BPF_REG_0].btf = field->list_head.btf; -+ regs[BPF_REG_0].btf_id = field->list_head.value_btf_id; -+ regs[BPF_REG_0].off = field->list_head.node_offset; - } else { - verbose(env, "kernel function %s unhandled dynamic return type\n", - meta.func_name); -@@ -13264,11 +13520,14 @@ static int do_check(struct bpf_verifier_env *env) - return -EINVAL; - } - -- if (env->cur_state->active_lock.ptr && -- (insn->src_reg == BPF_PSEUDO_CALL || -- insn->imm != BPF_FUNC_spin_unlock)) { -- verbose(env, "function calls are not allowed while holding a lock\n"); -- return -EINVAL; -+ if (env->cur_state->active_lock.ptr) { -+ if ((insn->src_reg == BPF_REG_0 && insn->imm != BPF_FUNC_spin_unlock) || -+ (insn->src_reg == BPF_PSEUDO_CALL) || -+ (insn->src_reg == BPF_PSEUDO_KFUNC_CALL && -+ (insn->off != 0 || !is_bpf_list_api_kfunc(insn->imm)))) { -+ verbose(env, "function calls are not allowed while holding a lock\n"); -+ return -EINVAL; -+ } - } - if (insn->src_reg == BPF_PSEUDO_CALL) - err = check_func_call(env, insn, &env->insn_idx); -diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h -index 8473395a11af..d6b143275e82 100644 ---- a/tools/testing/selftests/bpf/bpf_experimental.h -+++ b/tools/testing/selftests/bpf/bpf_experimental.h -@@ -35,4 +35,32 @@ extern void bpf_obj_drop_impl(void *kptr, void *meta) __ksym; - /* Convenience macro to wrap over bpf_obj_drop_impl */ - #define bpf_obj_drop(kptr) bpf_obj_drop_impl(kptr, NULL) - -+/* Description -+ * Add a new entry to the beginning of the BPF linked list. -+ * Returns -+ * Void. -+ */ -+extern void bpf_list_push_front(struct bpf_list_head *head, struct bpf_list_node *node) __ksym; -+ -+/* Description -+ * Add a new entry to the end of the BPF linked list. -+ * Returns -+ * Void. -+ */ -+extern void bpf_list_push_back(struct bpf_list_head *head, struct bpf_list_node *node) __ksym; -+ -+/* Description -+ * Remove the entry at the beginning of the BPF linked list. -+ * Returns -+ * Pointer to bpf_list_node of deleted entry, or NULL if list is empty. -+ */ -+extern struct bpf_list_node *bpf_list_pop_front(struct bpf_list_head *head) __ksym; -+ -+/* Description -+ * Remove the entry at the end of the BPF linked list. -+ * Returns -+ * Pointer to bpf_list_node of deleted entry, or NULL if list is empty. -+ */ -+extern struct bpf_list_node *bpf_list_pop_back(struct bpf_list_head *head) __ksym; -+ - #endif -</cut> diff --git a/jenkins/mail-recipients.draft b/jenkins/mail-recipients.draft deleted file mode 100644 index 3236d64..0000000 --- a/jenkins/mail-recipients.draft +++ /dev/null @@ -1 +0,0 @@ -Kumar Kartikeya Dwivedi <memxor@gmail.com>,cc:llvm@lists.linux.dev,cc:arnd@linaro.org diff --git a/jenkins/mail-subject.draft b/jenkins/mail-subject.draft deleted file mode 100644 index ef99524..0000000 --- a/jenkins/mail-subject.draft +++ /dev/null @@ -1 +0,0 @@ -[TCWG CI] Failure after v6.1-rc4-1107-g8cab76ec6349: bpf: Introduce single ownership BPF linked list API diff --git a/jenkins/notify.sh b/jenkins/notify.sh deleted file mode 100755 index e21359a..0000000 --- a/jenkins/notify.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -/home/tcwg-buildslave/workspace/tcwg_kernel_0/jenkins-scripts/round-robin-notify.sh --artifacts "artifacts/jenkins" --BUILD_URL "https://ci.linaro.org/job/tcwg_kernel-llvm-build-llvm-master-aarch64-mainline-allyesconfig/532/" --ci_project "tcwg_kernel" --ci_config "llvm-master-aarch64-mainline-allyesconfig" --current_project "linux" --first_bad "8cab76ec634995e59a8b6346bf8b835ab7fad3a3" --last_good "df57f38a0d081f05ec48ea5aa7ca0564918ed915" --summary "artifacts/mail/jira-body.txt" |