Re: [PATCH bpf-next 1/5] bpf: Add a ARG_PTR_TO_CONST_STR argument type

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Florent,

I love your patch! Perhaps something to improve:

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

url:    https://github.com/0day-ci/linux/commits/Florent-Revest/bpf-Add-a-ARG_PTR_TO_CONST_STR-argument-type/20210311-070306
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: openrisc-randconfig-r023-20210308 (attached as .config)
compiler: or1k-linux-gcc (GCC) 9.3.0
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/0day-ci/linux/commit/cbb95ec99fafe0955aeada270c9be3d1477c3866
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Florent-Revest/bpf-Add-a-ARG_PTR_TO_CONST_STR-argument-type/20210311-070306
        git checkout cbb95ec99fafe0955aeada270c9be3d1477c3866
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=openrisc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@xxxxxxxxx>

All warnings (new ones prefixed by >>):

   kernel/bpf/verifier.c: In function 'check_func_arg':
>> kernel/bpf/verifier.c:4918:13: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    4918 |   map_ptr = (char *)(map_addr);
         |             ^
   In file included from include/linux/bpf_verifier.h:9,
                    from kernel/bpf/verifier.c:12:
   kernel/bpf/verifier.c: In function 'jit_subprogs':
   include/linux/filter.h:363:4: warning: cast between incompatible function types from 'unsigned int (*)(const void *, const struct bpf_insn *)' to 'u64 (*)(u64,  u64,  u64,  u64,  u64)' {aka 'long long unsigned int (*)(long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int)'} [-Wcast-function-type]
     363 |   ((u64 (*)(u64, u64, u64, u64, u64))(x))
         |    ^
   kernel/bpf/verifier.c:11728:16: note: in expansion of macro 'BPF_CAST_CALL'
   11728 |    insn->imm = BPF_CAST_CALL(func[subprog]->bpf_func) -
         |                ^~~~~~~~~~~~~
   kernel/bpf/verifier.c: In function 'do_misc_fixups':
   include/linux/filter.h:363:4: warning: cast between incompatible function types from 'void * (* const)(struct bpf_map *, void *)' to 'u64 (*)(u64,  u64,  u64,  u64,  u64)' {aka 'long long unsigned int (*)(long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int)'} [-Wcast-function-type]
     363 |   ((u64 (*)(u64, u64, u64, u64, u64))(x))
         |    ^
   kernel/bpf/verifier.c:12136:17: note: in expansion of macro 'BPF_CAST_CALL'
   12136 |     insn->imm = BPF_CAST_CALL(ops->map_lookup_elem) -
         |                 ^~~~~~~~~~~~~
   include/linux/filter.h:363:4: warning: cast between incompatible function types from 'int (* const)(struct bpf_map *, void *, void *, u64)' {aka 'int (* const)(struct bpf_map *, void *, void *, long long unsigned int)'} to 'u64 (*)(u64,  u64,  u64,  u64,  u64)' {aka 'long long unsigned int (*)(long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int)'} [-Wcast-function-type]
     363 |   ((u64 (*)(u64, u64, u64, u64, u64))(x))
         |    ^
   kernel/bpf/verifier.c:12140:17: note: in expansion of macro 'BPF_CAST_CALL'
   12140 |     insn->imm = BPF_CAST_CALL(ops->map_update_elem) -
         |                 ^~~~~~~~~~~~~
   include/linux/filter.h:363:4: warning: cast between incompatible function types from 'int (* const)(struct bpf_map *, void *)' to 'u64 (*)(u64,  u64,  u64,  u64,  u64)' {aka 'long long unsigned int (*)(long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int)'} [-Wcast-function-type]
     363 |   ((u64 (*)(u64, u64, u64, u64, u64))(x))
         |    ^
   kernel/bpf/verifier.c:12144:17: note: in expansion of macro 'BPF_CAST_CALL'
   12144 |     insn->imm = BPF_CAST_CALL(ops->map_delete_elem) -
         |                 ^~~~~~~~~~~~~
   include/linux/filter.h:363:4: warning: cast between incompatible function types from 'int (* const)(struct bpf_map *, void *, u64)' {aka 'int (* const)(struct bpf_map *, void *, long long unsigned int)'} to 'u64 (*)(u64,  u64,  u64,  u64,  u64)' {aka 'long long unsigned int (*)(long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int)'} [-Wcast-function-type]
     363 |   ((u64 (*)(u64, u64, u64, u64, u64))(x))
         |    ^
   kernel/bpf/verifier.c:12148:17: note: in expansion of macro 'BPF_CAST_CALL'
   12148 |     insn->imm = BPF_CAST_CALL(ops->map_push_elem) -
         |                 ^~~~~~~~~~~~~
   include/linux/filter.h:363:4: warning: cast between incompatible function types from 'int (* const)(struct bpf_map *, void *)' to 'u64 (*)(u64,  u64,  u64,  u64,  u64)' {aka 'long long unsigned int (*)(long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int)'} [-Wcast-function-type]
     363 |   ((u64 (*)(u64, u64, u64, u64, u64))(x))
         |    ^
   kernel/bpf/verifier.c:12152:17: note: in expansion of macro 'BPF_CAST_CALL'
   12152 |     insn->imm = BPF_CAST_CALL(ops->map_pop_elem) -
         |                 ^~~~~~~~~~~~~
   include/linux/filter.h:363:4: warning: cast between incompatible function types from 'int (* const)(struct bpf_map *, void *)' to 'u64 (*)(u64,  u64,  u64,  u64,  u64)' {aka 'long long unsigned int (*)(long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int)'} [-Wcast-function-type]
     363 |   ((u64 (*)(u64, u64, u64, u64, u64))(x))
         |    ^
   kernel/bpf/verifier.c:12156:17: note: in expansion of macro 'BPF_CAST_CALL'
   12156 |     insn->imm = BPF_CAST_CALL(ops->map_peek_elem) -
         |                 ^~~~~~~~~~~~~
   include/linux/filter.h:363:4: warning: cast between incompatible function types from 'int (* const)(struct bpf_map *, u32,  u64)' {aka 'int (* const)(struct bpf_map *, unsigned int,  long long unsigned int)'} to 'u64 (*)(u64,  u64,  u64,  u64,  u64)' {aka 'long long unsigned int (*)(long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int,  long long unsigned int)'} [-Wcast-function-type]
     363 |   ((u64 (*)(u64, u64, u64, u64, u64))(x))
         |    ^
   kernel/bpf/verifier.c:12160:17: note: in expansion of macro 'BPF_CAST_CALL'
   12160 |     insn->imm = BPF_CAST_CALL(ops->map_redirect) -
         |                 ^~~~~~~~~~~~~


vim +4918 kernel/bpf/verifier.c

  4695	
  4696	static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
  4697				  struct bpf_call_arg_meta *meta,
  4698				  const struct bpf_func_proto *fn)
  4699	{
  4700		u32 regno = BPF_REG_1 + arg;
  4701		struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
  4702		enum bpf_arg_type arg_type = fn->arg_type[arg];
  4703		enum bpf_reg_type type = reg->type;
  4704		int err = 0;
  4705	
  4706		if (arg_type == ARG_DONTCARE)
  4707			return 0;
  4708	
  4709		err = check_reg_arg(env, regno, SRC_OP);
  4710		if (err)
  4711			return err;
  4712	
  4713		if (arg_type == ARG_ANYTHING) {
  4714			if (is_pointer_value(env, regno)) {
  4715				verbose(env, "R%d leaks addr into helper function\n",
  4716					regno);
  4717				return -EACCES;
  4718			}
  4719			return 0;
  4720		}
  4721	
  4722		if (type_is_pkt_pointer(type) &&
  4723		    !may_access_direct_pkt_data(env, meta, BPF_READ)) {
  4724			verbose(env, "helper access to the packet is not allowed\n");
  4725			return -EACCES;
  4726		}
  4727	
  4728		if (arg_type == ARG_PTR_TO_MAP_VALUE ||
  4729		    arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE ||
  4730		    arg_type == ARG_PTR_TO_MAP_VALUE_OR_NULL) {
  4731			err = resolve_map_arg_type(env, meta, &arg_type);
  4732			if (err)
  4733				return err;
  4734		}
  4735	
  4736		if (register_is_null(reg) && arg_type_may_be_null(arg_type))
  4737			/* A NULL register has a SCALAR_VALUE type, so skip
  4738			 * type checking.
  4739			 */
  4740			goto skip_type_check;
  4741	
  4742		err = check_reg_type(env, regno, arg_type, fn->arg_btf_id[arg]);
  4743		if (err)
  4744			return err;
  4745	
  4746		if (type == PTR_TO_CTX) {
  4747			err = check_ctx_reg(env, reg, regno);
  4748			if (err < 0)
  4749				return err;
  4750		}
  4751	
  4752	skip_type_check:
  4753		if (reg->ref_obj_id) {
  4754			if (meta->ref_obj_id) {
  4755				verbose(env, "verifier internal error: more than one arg with ref_obj_id R%d %u %u\n",
  4756					regno, reg->ref_obj_id,
  4757					meta->ref_obj_id);
  4758				return -EFAULT;
  4759			}
  4760			meta->ref_obj_id = reg->ref_obj_id;
  4761		}
  4762	
  4763		if (arg_type == ARG_CONST_MAP_PTR) {
  4764			/* bpf_map_xxx(map_ptr) call: remember that map_ptr */
  4765			meta->map_ptr = reg->map_ptr;
  4766		} else if (arg_type == ARG_PTR_TO_MAP_KEY) {
  4767			/* bpf_map_xxx(..., map_ptr, ..., key) call:
  4768			 * check that [key, key + map->key_size) are within
  4769			 * stack limits and initialized
  4770			 */
  4771			if (!meta->map_ptr) {
  4772				/* in function declaration map_ptr must come before
  4773				 * map_key, so that it's verified and known before
  4774				 * we have to check map_key here. Otherwise it means
  4775				 * that kernel subsystem misconfigured verifier
  4776				 */
  4777				verbose(env, "invalid map_ptr to access map->key\n");
  4778				return -EACCES;
  4779			}
  4780			err = check_helper_mem_access(env, regno,
  4781						      meta->map_ptr->key_size, false,
  4782						      NULL);
  4783		} else if (arg_type == ARG_PTR_TO_MAP_VALUE ||
  4784			   (arg_type == ARG_PTR_TO_MAP_VALUE_OR_NULL &&
  4785			    !register_is_null(reg)) ||
  4786			   arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE) {
  4787			/* bpf_map_xxx(..., map_ptr, ..., value) call:
  4788			 * check [value, value + map->value_size) validity
  4789			 */
  4790			if (!meta->map_ptr) {
  4791				/* kernel subsystem misconfigured verifier */
  4792				verbose(env, "invalid map_ptr to access map->value\n");
  4793				return -EACCES;
  4794			}
  4795			meta->raw_mode = (arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE);
  4796			err = check_helper_mem_access(env, regno,
  4797						      meta->map_ptr->value_size, false,
  4798						      meta);
  4799		} else if (arg_type == ARG_PTR_TO_PERCPU_BTF_ID) {
  4800			if (!reg->btf_id) {
  4801				verbose(env, "Helper has invalid btf_id in R%d\n", regno);
  4802				return -EACCES;
  4803			}
  4804			meta->ret_btf = reg->btf;
  4805			meta->ret_btf_id = reg->btf_id;
  4806		} else if (arg_type == ARG_PTR_TO_SPIN_LOCK) {
  4807			if (meta->func_id == BPF_FUNC_spin_lock) {
  4808				if (process_spin_lock(env, regno, true))
  4809					return -EACCES;
  4810			} else if (meta->func_id == BPF_FUNC_spin_unlock) {
  4811				if (process_spin_lock(env, regno, false))
  4812					return -EACCES;
  4813			} else {
  4814				verbose(env, "verifier internal error\n");
  4815				return -EFAULT;
  4816			}
  4817		} else if (arg_type == ARG_PTR_TO_FUNC) {
  4818			meta->subprogno = reg->subprogno;
  4819		} else if (arg_type_is_mem_ptr(arg_type)) {
  4820			/* The access to this pointer is only checked when we hit the
  4821			 * next is_mem_size argument below.
  4822			 */
  4823			meta->raw_mode = (arg_type == ARG_PTR_TO_UNINIT_MEM);
  4824		} else if (arg_type_is_mem_size(arg_type)) {
  4825			bool zero_size_allowed = (arg_type == ARG_CONST_SIZE_OR_ZERO);
  4826	
  4827			/* This is used to refine r0 return value bounds for helpers
  4828			 * that enforce this value as an upper bound on return values.
  4829			 * See do_refine_retval_range() for helpers that can refine
  4830			 * the return value. C type of helper is u32 so we pull register
  4831			 * bound from umax_value however, if negative verifier errors
  4832			 * out. Only upper bounds can be learned because retval is an
  4833			 * int type and negative retvals are allowed.
  4834			 */
  4835			meta->msize_max_value = reg->umax_value;
  4836	
  4837			/* The register is SCALAR_VALUE; the access check
  4838			 * happens using its boundaries.
  4839			 */
  4840			if (!tnum_is_const(reg->var_off))
  4841				/* For unprivileged variable accesses, disable raw
  4842				 * mode so that the program is required to
  4843				 * initialize all the memory that the helper could
  4844				 * just partially fill up.
  4845				 */
  4846				meta = NULL;
  4847	
  4848			if (reg->smin_value < 0) {
  4849				verbose(env, "R%d min value is negative, either use unsigned or 'var &= const'\n",
  4850					regno);
  4851				return -EACCES;
  4852			}
  4853	
  4854			if (reg->umin_value == 0) {
  4855				err = check_helper_mem_access(env, regno - 1, 0,
  4856							      zero_size_allowed,
  4857							      meta);
  4858				if (err)
  4859					return err;
  4860			}
  4861	
  4862			if (reg->umax_value >= BPF_MAX_VAR_SIZ) {
  4863				verbose(env, "R%d unbounded memory access, use 'var &= const' or 'if (var < const)'\n",
  4864					regno);
  4865				return -EACCES;
  4866			}
  4867			err = check_helper_mem_access(env, regno - 1,
  4868						      reg->umax_value,
  4869						      zero_size_allowed, meta);
  4870			if (!err)
  4871				err = mark_chain_precision(env, regno);
  4872		} else if (arg_type_is_alloc_size(arg_type)) {
  4873			if (!tnum_is_const(reg->var_off)) {
  4874				verbose(env, "R%d is not a known constant'\n",
  4875					regno);
  4876				return -EACCES;
  4877			}
  4878			meta->mem_size = reg->var_off.value;
  4879		} else if (arg_type_is_int_ptr(arg_type)) {
  4880			int size = int_ptr_type_to_size(arg_type);
  4881	
  4882			err = check_helper_mem_access(env, regno, size, false, meta);
  4883			if (err)
  4884				return err;
  4885			err = check_ptr_alignment(env, reg, 0, size, true);
  4886		} else if (arg_type == ARG_PTR_TO_CONST_STR) {
  4887			struct bpf_map *map = reg->map_ptr;
  4888			int map_off, i;
  4889			u64 map_addr;
  4890			char *map_ptr;
  4891	
  4892			if (!map || !bpf_map_is_rdonly(map)) {
  4893				verbose(env, "R%d does not point to a readonly map'\n", regno);
  4894				return -EACCES;
  4895			}
  4896	
  4897			if (!tnum_is_const(reg->var_off)) {
  4898				verbose(env, "R%d is not a constant address'\n", regno);
  4899				return -EACCES;
  4900			}
  4901	
  4902			if (!map->ops->map_direct_value_addr) {
  4903				verbose(env, "no direct value access support for this map type\n");
  4904				return -EACCES;
  4905			}
  4906	
  4907			err = check_helper_mem_access(env, regno,
  4908						      map->value_size - reg->off,
  4909						      false, meta);
  4910			if (err)
  4911				return err;
  4912	
  4913			map_off = reg->off + reg->var_off.value;
  4914			err = map->ops->map_direct_value_addr(map, &map_addr, map_off);
  4915			if (err)
  4916				return err;
  4917	
> 4918			map_ptr = (char *)(map_addr);
  4919			for (i = map_off; map_ptr[i] != '\0'; i++) {
  4920				if (i == map->value_size - 1) {
  4921					verbose(env, "map does not contain a NULL-terminated string\n");
  4922					return -EACCES;
  4923				}
  4924			}
  4925		}
  4926	
  4927		return err;
  4928	}
  4929	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@xxxxxxxxxxxx

Attachment: .config.gz
Description: application/gzip


[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux