Re: [PATCH v12 bpf-next 09/10] bpf: Add bpf_dynptr_slice and bpf_dynptr_slice_rdwr

kernel test robot
2023-02-26T10:56:02Z

Hi Joanne,

Thank you for the patch! Yet something to improve:

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

url: https://github.com/intel-lab-lkp/linux/commits/Joanne-Koong/bpf-Support-sk_buff-and-xdp_buff-as-valid-kfunc-arg-types/20230226-165406
base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
patch link: https://lore.kernel.org/r/20230226085120.3907863-10-joannelkoong%40gmail.com
patch subject: [PATCH v12 bpf-next 09/10] bpf: Add bpf_dynptr_slice and bpf_dynptr_slice_rdwr
config: hexagon-randconfig-r026-20230226 (https://download.01.org/0day-ci/archive/20230226/202302261821.69VtQP9g-lkp@intel.com/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project db89896bbbd2251fff457699635acbbedeead27f)
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
# https://github.com/intel-lab-lkp/linux/commit/bc5a61c43c72539ef11e6435a168bf240a186ac1
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Joanne-Koong/bpf-Support-sk_buff-and-xdp_buff-as-valid-kfunc-arg-types/20230226-165406
git checkout bc5a61c43c72539ef11e6435a168bf240a186ac1
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202302261821.69VtQP9g-lkp@intel.com/

All errors (new ones prefixed by >>):

In file included from kernel/bpf/verifier.c:7:
In file included from include/linux/bpf-cgroup.h:5:
In file included from include/linux/bpf.h:31:
In file included from include/linux/memcontrol.h:13:
In file included from include/linux/cgroup.h:26:
In file included from include/linux/kernel_stat.h:9:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/hexagon/include/asm/io.h:334:
include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __raw_readb(PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
#define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
^
In file included from kernel/bpf/verifier.c:7:
In file included from include/linux/bpf-cgroup.h:5:
In file included from include/linux/bpf.h:31:
In file included from include/linux/memcontrol.h:13:
In file included from include/linux/cgroup.h:26:
In file included from include/linux/kernel_stat.h:9:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/hexagon/include/asm/io.h:334:
include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
#define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
^
In file included from kernel/bpf/verifier.c:7:
In file included from include/linux/bpf-cgroup.h:5:
In file included from include/linux/bpf.h:31:
In file included from include/linux/memcontrol.h:13:
In file included from include/linux/cgroup.h:26:
In file included from include/linux/kernel_stat.h:9:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/hexagon/include/asm/io.h:334:
include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writeb(value, PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
~~~~~~~~~~ ^
kernel/bpf/verifier.c:6253:5: warning: no previous prototype for function 'process_dynptr_func' [-Wmissing-prototypes]
int process_dynptr_func(struct bpf_verifier_env *env, int regno, int insn_idx,
^
kernel/bpf/verifier.c:6253:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
int process_dynptr_func(struct bpf_verifier_env *env, int regno, int insn_idx,
^
static
>> kernel/bpf/verifier.c:9907:4: error: expected expression
struct bpf_reg_state *size_reg = &regs[regno + 1];
^
>> kernel/bpf/verifier.c:9910:40: error: use of undeclared identifier 'size_reg'; did you mean 'size_arg'?
ret = check_kfunc_mem_size_reg(env, size_reg, regno + 1);
^~~~~~~~
size_arg
kernel/bpf/verifier.c:9908:28: note: 'size_arg' declared here
const struct btf_param *size_arg = &args[i + 1];
^
kernel/bpf/verifier.c:9916:57: error: use of undeclared identifier 'size_reg'; did you mean 'size_arg'?
if (is_kfunc_arg_const_mem_size(meta->btf, size_arg, size_reg)) {
^~~~~~~~
size_arg
kernel/bpf/verifier.c:9908:28: note: 'size_arg' declared here
const struct btf_param *size_arg = &args[i + 1];
^
kernel/bpf/verifier.c:9921:24: error: use of undeclared identifier 'size_reg'
if (!tnum_is_const(size_reg->var_off)) {
^
kernel/bpf/verifier.c:9926:32: error: use of undeclared identifier 'size_reg'
meta->arg_constant.value = size_reg->var_off.value;
^
kernel/bpf/verifier.c:9908:28: warning: mixing declarations and code is incompatible with standards before C99 [-Wdeclaration-after-statement]
const struct btf_param *size_arg = &args[i + 1];
^
8 warnings and 5 errors generated.

vim +9907 kernel/bpf/verifier.c

9584
9585 static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_arg_meta *meta,
9586 int insn_idx)
9587 {
9588 const char *func_name = meta->func_name, *ref_tname;
9589 const struct btf *btf = meta->btf;
9590 const struct btf_param *args;
9591 u32 i, nargs;
9592 int ret;
9593
9594 args = (const struct btf_param *)(meta->func_proto + 1);
9595 nargs = btf_type_vlen(meta->func_proto);
9596 if (nargs > MAX_BPF_FUNC_REG_ARGS) {
9597 verbose(env, "Function %s has %d > %d args\n", func_name, nargs,
9598 MAX_BPF_FUNC_REG_ARGS);
9599 return -EINVAL;
9600 }
9601
9602 /* Check that BTF function arguments match actual types that the
9603 * verifier sees.
9604 */
9605 for (i = 0; i < nargs; i++) {
9606 struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[i + 1];
9607 const struct btf_type *t, *ref_t, *resolve_ret;
9608 enum bpf_arg_type arg_type = ARG_DONTCARE;
9609 u32 regno = i + 1, ref_id, type_size;
9610 bool is_ret_buf_sz = false;
9611 int kf_arg_type;
9612
9613 t = btf_type_skip_modifiers(btf, args[i].type, NULL);
9614
9615 if (is_kfunc_arg_ignore(btf, &args[i]))
9616 continue;
9617
9618 if (btf_type_is_scalar(t)) {
9619 if (reg->type != SCALAR_VALUE) {
9620 verbose(env, "R%d is not a scalar\n", regno);
9621 return -EINVAL;
9622 }
9623
9624 if (is_kfunc_arg_constant(meta->btf, &args[i])) {
9625 if (meta->arg_constant.found) {
9626 verbose(env, "verifier internal error: only one constant argument permitted\n");
9627 return -EFAULT;
9628 }
9629 if (!tnum_is_const(reg->var_off)) {
9630 verbose(env, "R%d must be a known constant\n", regno);
9631 return -EINVAL;
9632 }
9633 ret = mark_chain_precision(env, regno);
9634 if (ret < 0)
9635 return ret;
9636 meta->arg_constant.found = true;
9637 meta->arg_constant.value = reg->var_off.value;
9638 } else if (is_kfunc_arg_scalar_with_name(btf, &args[i], "rdonly_buf_size")) {
9639 meta->r0_rdonly = true;
9640 is_ret_buf_sz = true;
9641 } else if (is_kfunc_arg_scalar_with_name(btf, &args[i], "rdwr_buf_size")) {
9642 is_ret_buf_sz = true;
9643 }
9644
9645 if (is_ret_buf_sz) {
9646 if (meta->r0_size) {
9647 verbose(env, "2 or more rdonly/rdwr_buf_size parameters for kfunc");
9648 return -EINVAL;
9649 }
9650
9651 if (!tnum_is_const(reg->var_off)) {
9652 verbose(env, "R%d is not a const\n", regno);
9653 return -EINVAL;
9654 }
9655
9656 meta->r0_size = reg->var_off.value;
9657 ret = mark_chain_precision(env, regno);
9658 if (ret)
9659 return ret;
9660 }
9661 continue;
9662 }
9663
9664 if (!btf_type_is_ptr(t)) {
9665 verbose(env, "Unrecognized arg#%d type %s\n", i, btf_type_str(t));
9666 return -EINVAL;
9667 }
9668
9669 if (is_kfunc_trusted_args(meta) &&
9670 (register_is_null(reg) || type_may_be_null(reg->type))) {
9671 verbose(env, "Possibly NULL pointer passed to trusted arg%d\n", i);
9672 return -EACCES;
9673 }
9674
9675 if (reg->ref_obj_id) {
9676 if (is_kfunc_release(meta) && meta->ref_obj_id) {
9677 verbose(env, "verifier internal error: more than one arg with ref_obj_id R%d %u %u\n",
9678 regno, reg->ref_obj_id,
9679 meta->ref_obj_id);
9680 return -EFAULT;
9681 }
9682 meta->ref_obj_id = reg->ref_obj_id;
9683 if (is_kfunc_release(meta))
9684 meta->release_regno = regno;
9685 }
9686
9687 ref_t = btf_type_skip_modifiers(btf, t->type, &ref_id);
9688 ref_tname = btf_name_by_offset(btf, ref_t->name_off);
9689
9690 kf_arg_type = get_kfunc_ptr_arg_type(env, meta, t, ref_t, ref_tname, args, i, nargs);
9691 if (kf_arg_type < 0)
9692 return kf_arg_type;
9693
9694 switch (kf_arg_type) {
9695 case KF_ARG_PTR_TO_ALLOC_BTF_ID:
9696 case KF_ARG_PTR_TO_BTF_ID:
9697 if (!is_kfunc_trusted_args(meta) && !is_kfunc_rcu(meta))
9698 break;
9699
9700 if (!is_trusted_reg(reg)) {
9701 if (!is_kfunc_rcu(meta)) {
9702 verbose(env, "R%d must be referenced or trusted\n", regno);
9703 return -EINVAL;
9704 }
9705 if (!is_rcu_reg(reg)) {
9706 verbose(env, "R%d must be a rcu pointer\n", regno);
9707 return -EINVAL;
9708 }
9709 }
9710
9711 fallthrough;
9712 case KF_ARG_PTR_TO_CTX:
9713 /* Trusted arguments have the same offset checks as release arguments */
9714 arg_type |= OBJ_RELEASE;
9715 break;
9716 case KF_ARG_PTR_TO_KPTR:
9717 case KF_ARG_PTR_TO_DYNPTR:
9718 case KF_ARG_PTR_TO_LIST_HEAD:
9719 case KF_ARG_PTR_TO_LIST_NODE:
9720 case KF_ARG_PTR_TO_RB_ROOT:
9721 case KF_ARG_PTR_TO_RB_NODE:
9722 case KF_ARG_PTR_TO_MEM:
9723 case KF_ARG_PTR_TO_MEM_SIZE:
9724 case KF_ARG_PTR_TO_CALLBACK:
9725 /* Trusted by default */
9726 break;
9727 default:
9728 WARN_ON_ONCE(1);
9729 return -EFAULT;
9730 }
9731
9732 if (is_kfunc_release(meta) && reg->ref_obj_id)
9733 arg_type |= OBJ_RELEASE;
9734 ret = check_func_arg_reg_off(env, reg, regno, arg_type);
9735 if (ret < 0)
9736 return ret;
9737
9738 switch (kf_arg_type) {
9739 case KF_ARG_PTR_TO_CTX:
9740 if (reg->type != PTR_TO_CTX) {
9741 verbose(env, "arg#%d expected pointer to ctx, but got %s\n", i, btf_type_str(t));
9742 return -EINVAL;
9743 }
9744
9745 if (meta->func_id == special_kfunc_list[KF_bpf_cast_to_kern_ctx]) {
9746 ret = get_kern_ctx_btf_id(&env->log, resolve_prog_type(env->prog));
9747 if (ret < 0)
9748 return -EINVAL;
9749 meta->ret_btf_id = ret;
9750 }
9751 break;
9752 case KF_ARG_PTR_TO_ALLOC_BTF_ID:
9753 if (reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
9754 verbose(env, "arg#%d expected pointer to allocated object\n", i);
9755 return -EINVAL;
9756 }
9757 if (!reg->ref_obj_id) {
9758 verbose(env, "allocated object must be referenced\n");
9759 return -EINVAL;
9760 }
9761 if (meta->btf == btf_vmlinux &&
9762 meta->func_id == special_kfunc_list[KF_bpf_obj_drop_impl]) {
9763 meta->arg_obj_drop.btf = reg->btf;
9764 meta->arg_obj_drop.btf_id = reg->btf_id;
9765 }
9766 break;
9767 case KF_ARG_PTR_TO_KPTR:
9768 if (reg->type != PTR_TO_MAP_VALUE) {
9769 verbose(env, "arg#0 expected pointer to map value\n");
9770 return -EINVAL;
9771 }
9772 ret = process_kf_arg_ptr_to_kptr(env, reg, ref_t, ref_tname, meta, i);
9773 if (ret < 0)
9774 return ret;
9775 break;
9776 case KF_ARG_PTR_TO_DYNPTR:
9777 {
9778 enum bpf_arg_type dynptr_arg_type = ARG_PTR_TO_DYNPTR;
9779
9780 if (reg->type != PTR_TO_STACK &&
9781 reg->type != CONST_PTR_TO_DYNPTR) {
9782 verbose(env, "arg#%d expected pointer to stack or dynptr_ptr\n", i);
9783 return -EINVAL;
9784 }
9785
9786 if (reg->type == CONST_PTR_TO_DYNPTR)
9787 dynptr_arg_type |= MEM_RDONLY;
9788
9789 if (is_kfunc_arg_uninit(btf, &args[i]))
9790 dynptr_arg_type |= MEM_UNINIT;
9791
9792 if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb])
9793 dynptr_arg_type |= DYNPTR_TYPE_SKB;
9794 else if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_xdp])
9795 dynptr_arg_type |= DYNPTR_TYPE_XDP;
9796
9797 ret = process_dynptr_func(env, regno, insn_idx, dynptr_arg_type);
9798 if (ret < 0)
9799 return ret;
9800
9801 if (!(dynptr_arg_type & MEM_UNINIT)) {
9802 int id = dynptr_id(env, reg);
9803
9804 if (id < 0) {
9805 verbose(env, "verifier internal error: failed to obtain dynptr id\n");
9806 return id;
9807 }
9808 meta->initialized_dynptr.id = id;
9809 meta->initialized_dynptr.type = dynptr_get_type(env, reg);
9810 }
9811
9812 break;
9813 }
9814 case KF_ARG_PTR_TO_LIST_HEAD:
9815 if (reg->type != PTR_TO_MAP_VALUE &&
9816 reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
9817 verbose(env, "arg#%d expected pointer to map value or allocated object\n", i);
9818 return -EINVAL;
9819 }
9820 if (reg->type == (PTR_TO_BTF_ID | MEM_ALLOC) && !reg->ref_obj_id) {
9821 verbose(env, "allocated object must be referenced\n");
9822 return -EINVAL;
9823 }
9824 ret = process_kf_arg_ptr_to_list_head(env, reg, regno, meta);
9825 if (ret < 0)
9826 return ret;
9827 break;
9828 case KF_ARG_PTR_TO_RB_ROOT:
9829 if (reg->type != PTR_TO_MAP_VALUE &&
9830 reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
9831 verbose(env, "arg#%d expected pointer to map value or allocated object\n", i);
9832 return -EINVAL;
9833 }
9834 if (reg->type == (PTR_TO_BTF_ID | MEM_ALLOC) && !reg->ref_obj_id) {
9835 verbose(env, "allocated object must be referenced\n");
9836 return -EINVAL;
9837 }
9838 ret = process_kf_arg_ptr_to_rbtree_root(env, reg, regno, meta);
9839 if (ret < 0)
9840 return ret;
9841 break;
9842 case KF_ARG_PTR_TO_LIST_NODE:
9843 if (reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
9844 verbose(env, "arg#%d expected pointer to allocated object\n", i);
9845 return -EINVAL;
9846 }
9847 if (!reg->ref_obj_id) {
9848 verbose(env, "allocated object must be referenced\n");
9849 return -EINVAL;
9850 }
9851 ret = process_kf_arg_ptr_to_list_node(env, reg, regno, meta);
9852 if (ret < 0)
9853 return ret;
9854 break;
9855 case KF_ARG_PTR_TO_RB_NODE:
9856 if (meta->func_id == special_kfunc_list[KF_bpf_rbtree_remove]) {
9857 if (!type_is_non_owning_ref(reg->type) || reg->ref_obj_id) {
9858 verbose(env, "rbtree_remove node input must be non-owning ref\n");
9859 return -EINVAL;
9860 }
9861 if (in_rbtree_lock_required_cb(env)) {
9862 verbose(env, "rbtree_remove not allowed in rbtree cb\n");
9863 return -EINVAL;
9864 }
9865 } else {
9866 if (reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
9867 verbose(env, "arg#%d expected pointer to allocated object\n", i);
9868 return -EINVAL;
9869 }
9870 if (!reg->ref_obj_id) {
9871 verbose(env, "allocated object must be referenced\n");
9872 return -EINVAL;
9873 }
9874 }
9875
9876 ret = process_kf_arg_ptr_to_rbtree_node(env, reg, regno, meta);
9877 if (ret < 0)
9878 return ret;
9879 break;
9880 case KF_ARG_PTR_TO_BTF_ID:
9881 /* Only base_type is checked, further checks are done here */
9882 if ((base_type(reg->type) != PTR_TO_BTF_ID ||
9883 (bpf_type_has_unsafe_modifiers(reg->type) && !is_rcu_reg(reg))) &&
9884 !reg2btf_ids[base_type(reg->type)]) {
9885 verbose(env, "arg#%d is %s ", i, reg_type_str(env, reg->type));
9886 verbose(env, "expected %s or socket\n",
9887 reg_type_str(env, base_type(reg->type) |
9888 (type_flag(reg->type) & BPF_REG_TRUSTED_MODIFIERS)));
9889 return -EINVAL;
9890 }
9891 ret = process_kf_arg_ptr_to_btf_id(env, reg, ref_t, ref_tname, ref_id, meta, i);
9892 if (ret < 0)
9893 return ret;
9894 break;
9895 case KF_ARG_PTR_TO_MEM:
9896 resolve_ret = btf_resolve_size(btf, ref_t, &type_size);
9897 if (IS_ERR(resolve_ret)) {
9898 verbose(env, "arg#%d reference type('%s %s') size cannot be determined: %ld\n",
9899 i, btf_type_str(ref_t), ref_tname, PTR_ERR(resolve_ret));
9900 return -EINVAL;
9901 }
9902 ret = check_mem_reg(env, reg, regno, type_size);
9903 if (ret < 0)
9904 return ret;
9905 break;
9906 case KF_ARG_PTR_TO_MEM_SIZE:
> 9907 struct bpf_reg_state *size_reg = &regs[regno + 1];
9908 const struct btf_param *size_arg = &args[i + 1];
9909
> 9910 ret = check_kfunc_mem_size_reg(env, size_reg, regno + 1);
9911 if (ret < 0) {
9912 verbose(env, "arg#%d arg#%d memory, len pair leads to invalid memory access\n", i, i + 1);
9913 return ret;
9914 }
9915
9916 if (is_kfunc_arg_const_mem_size(meta->btf, size_arg, size_reg)) {
9917 if (meta->arg_constant.found) {
9918 verbose(env, "verifier internal error: only one constant argument permitted\n");
9919 return -EFAULT;
9920 }
9921 if (!tnum_is_const(size_reg->var_off)) {
9922 verbose(env, "R%d must be a known constant\n", regno + 1);
9923 return -EINVAL;
9924 }
9925 meta->arg_constant.found = true;
9926 meta->arg_constant.value = size_reg->var_off.value;
9927 }
9928
9929 /* Skip next '__sz' or '__szk' argument */
9930 i++;
9931 break;
9932 case KF_ARG_PTR_TO_CALLBACK:
9933 meta->subprogno = reg->subprogno;
9934 break;
9935 }
9936 }
9937
9938 if (is_kfunc_release(meta) && !meta->release_regno) {
9939 verbose(env, "release kernel function %s expects refcounted PTR_TO_BTF_ID\n",
9940 func_name);
9941 return -EINVAL;
9942 }
9943
9944 return 0;
9945 }
9946

--
0-DAY CI Kernel Test Service