forked from mirrors/linux
		
	bpf: check bpf_dummy_struct_ops program params for test runs
When doing BPF_PROG_TEST_RUN for bpf_dummy_struct_ops programs, reject execution when NULL is passed for non-nullable params. For programs with non-nullable params verifier assumes that such params are never NULL and thus might optimize out NULL checks. Suggested-by: Kui-Feng Lee <sinquersw@gmail.com> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20240424012821.595216-5-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
		
							parent
							
								
									f612210d45
								
							
						
					
					
						commit
						980ca8ceea
					
				
					 1 changed files with 50 additions and 1 deletions
				
			
		|  | @ -79,6 +79,51 @@ static int dummy_ops_call_op(void *image, struct bpf_dummy_ops_test_args *args) | ||||||
| 		    args->args[3], args->args[4]); | 		    args->args[3], args->args[4]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const struct bpf_ctx_arg_aux *find_ctx_arg_info(struct bpf_prog_aux *aux, int offset) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < aux->ctx_arg_info_size; i++) | ||||||
|  | 		if (aux->ctx_arg_info[i].offset == offset) | ||||||
|  | 			return &aux->ctx_arg_info[i]; | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* There is only one check at the moment:
 | ||||||
|  |  * - zero should not be passed for pointer parameters not marked as nullable. | ||||||
|  |  */ | ||||||
|  | static int check_test_run_args(struct bpf_prog *prog, struct bpf_dummy_ops_test_args *args) | ||||||
|  | { | ||||||
|  | 	const struct btf_type *func_proto = prog->aux->attach_func_proto; | ||||||
|  | 
 | ||||||
|  | 	for (u32 arg_no = 0; arg_no < btf_type_vlen(func_proto) ; ++arg_no) { | ||||||
|  | 		const struct btf_param *param = &btf_params(func_proto)[arg_no]; | ||||||
|  | 		const struct bpf_ctx_arg_aux *info; | ||||||
|  | 		const struct btf_type *t; | ||||||
|  | 		int offset; | ||||||
|  | 
 | ||||||
|  | 		if (args->args[arg_no] != 0) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		/* Program is validated already, so there is no need
 | ||||||
|  | 		 * to check if t is NULL. | ||||||
|  | 		 */ | ||||||
|  | 		t = btf_type_skip_modifiers(bpf_dummy_ops_btf, param->type, NULL); | ||||||
|  | 		if (!btf_type_is_ptr(t)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		offset = btf_ctx_arg_offset(bpf_dummy_ops_btf, func_proto, arg_no); | ||||||
|  | 		info = find_ctx_arg_info(prog->aux, offset); | ||||||
|  | 		if (info && (info->reg_type & PTR_MAYBE_NULL)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| extern const struct bpf_link_ops bpf_struct_ops_link_lops; | extern const struct bpf_link_ops bpf_struct_ops_link_lops; | ||||||
| 
 | 
 | ||||||
| int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, | int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, | ||||||
|  | @ -87,7 +132,7 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, | ||||||
| 	const struct bpf_struct_ops *st_ops = &bpf_bpf_dummy_ops; | 	const struct bpf_struct_ops *st_ops = &bpf_bpf_dummy_ops; | ||||||
| 	const struct btf_type *func_proto; | 	const struct btf_type *func_proto; | ||||||
| 	struct bpf_dummy_ops_test_args *args; | 	struct bpf_dummy_ops_test_args *args; | ||||||
| 	struct bpf_tramp_links *tlinks; | 	struct bpf_tramp_links *tlinks = NULL; | ||||||
| 	struct bpf_tramp_link *link = NULL; | 	struct bpf_tramp_link *link = NULL; | ||||||
| 	void *image = NULL; | 	void *image = NULL; | ||||||
| 	unsigned int op_idx; | 	unsigned int op_idx; | ||||||
|  | @ -109,6 +154,10 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, | ||||||
| 	if (IS_ERR(args)) | 	if (IS_ERR(args)) | ||||||
| 		return PTR_ERR(args); | 		return PTR_ERR(args); | ||||||
| 
 | 
 | ||||||
|  | 	err = check_test_run_args(prog, args); | ||||||
|  | 	if (err) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
| 	tlinks = kcalloc(BPF_TRAMP_MAX, sizeof(*tlinks), GFP_KERNEL); | 	tlinks = kcalloc(BPF_TRAMP_MAX, sizeof(*tlinks), GFP_KERNEL); | ||||||
| 	if (!tlinks) { | 	if (!tlinks) { | ||||||
| 		err = -ENOMEM; | 		err = -ENOMEM; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Eduard Zingerman
						Eduard Zingerman