mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	bpf: Add bpf_btf_find_by_name_kind() helper.
Add new helper: long bpf_btf_find_by_name_kind(char *name, int name_sz, u32 kind, int flags) Description Find BTF type with given name and kind in vmlinux BTF or in module's BTFs. Return Returns btf_id and btf_obj_fd in lower and upper 32 bits. It will be used by loader program to find btf_id to attach the program to and to find btf_ids of ksyms. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20210514003623.28033-10-alexei.starovoitov@gmail.com
This commit is contained in:
		
							parent
							
								
									387544bfa2
								
							
						
					
					
						commit
						3d78417b60
					
				
					 5 changed files with 79 additions and 0 deletions
				
			
		| 
						 | 
					@ -1974,6 +1974,7 @@ extern const struct bpf_func_proto bpf_get_socket_ptr_cookie_proto;
 | 
				
			||||||
extern const struct bpf_func_proto bpf_task_storage_get_proto;
 | 
					extern const struct bpf_func_proto bpf_task_storage_get_proto;
 | 
				
			||||||
extern const struct bpf_func_proto bpf_task_storage_delete_proto;
 | 
					extern const struct bpf_func_proto bpf_task_storage_delete_proto;
 | 
				
			||||||
extern const struct bpf_func_proto bpf_for_each_map_elem_proto;
 | 
					extern const struct bpf_func_proto bpf_for_each_map_elem_proto;
 | 
				
			||||||
 | 
					extern const struct bpf_func_proto bpf_btf_find_by_name_kind_proto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct bpf_func_proto *bpf_tracing_func_proto(
 | 
					const struct bpf_func_proto *bpf_tracing_func_proto(
 | 
				
			||||||
	enum bpf_func_id func_id, const struct bpf_prog *prog);
 | 
						enum bpf_func_id func_id, const struct bpf_prog *prog);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4748,6 +4748,12 @@ union bpf_attr {
 | 
				
			||||||
 * 		Execute bpf syscall with given arguments.
 | 
					 * 		Execute bpf syscall with given arguments.
 | 
				
			||||||
 * 	Return
 | 
					 * 	Return
 | 
				
			||||||
 * 		A syscall result.
 | 
					 * 		A syscall result.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * long bpf_btf_find_by_name_kind(char *name, int name_sz, u32 kind, int flags)
 | 
				
			||||||
 | 
					 * 	Description
 | 
				
			||||||
 | 
					 * 		Find BTF type with given name and kind in vmlinux BTF or in module's BTFs.
 | 
				
			||||||
 | 
					 * 	Return
 | 
				
			||||||
 | 
					 * 		Returns btf_id and btf_obj_fd in lower and upper 32 bits.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define __BPF_FUNC_MAPPER(FN)		\
 | 
					#define __BPF_FUNC_MAPPER(FN)		\
 | 
				
			||||||
	FN(unspec),			\
 | 
						FN(unspec),			\
 | 
				
			||||||
| 
						 | 
					@ -4917,6 +4923,7 @@ union bpf_attr {
 | 
				
			||||||
	FN(for_each_map_elem),		\
 | 
						FN(for_each_map_elem),		\
 | 
				
			||||||
	FN(snprintf),			\
 | 
						FN(snprintf),			\
 | 
				
			||||||
	FN(sys_bpf),			\
 | 
						FN(sys_bpf),			\
 | 
				
			||||||
 | 
						FN(btf_find_by_name_kind),	\
 | 
				
			||||||
	/* */
 | 
						/* */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
 | 
					/* integer value in 'imm' field of BPF_CALL instruction selects which helper
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6085,3 +6085,65 @@ struct module *btf_try_get_module(const struct btf *btf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BPF_CALL_4(bpf_btf_find_by_name_kind, char *, name, int, name_sz, u32, kind, int, flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct btf *btf;
 | 
				
			||||||
 | 
						long ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (flags)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (name_sz <= 1 || name[name_sz - 1])
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						btf = bpf_get_btf_vmlinux();
 | 
				
			||||||
 | 
						if (IS_ERR(btf))
 | 
				
			||||||
 | 
							return PTR_ERR(btf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = btf_find_by_name_kind(btf, name, kind);
 | 
				
			||||||
 | 
						/* ret is never zero, since btf_find_by_name_kind returns
 | 
				
			||||||
 | 
						 * positive btf_id or negative error.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							struct btf *mod_btf;
 | 
				
			||||||
 | 
							int id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* If name is not found in vmlinux's BTF then search in module's BTFs */
 | 
				
			||||||
 | 
							spin_lock_bh(&btf_idr_lock);
 | 
				
			||||||
 | 
							idr_for_each_entry(&btf_idr, mod_btf, id) {
 | 
				
			||||||
 | 
								if (!btf_is_module(mod_btf))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								/* linear search could be slow hence unlock/lock
 | 
				
			||||||
 | 
								 * the IDR to avoiding holding it for too long
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								btf_get(mod_btf);
 | 
				
			||||||
 | 
								spin_unlock_bh(&btf_idr_lock);
 | 
				
			||||||
 | 
								ret = btf_find_by_name_kind(mod_btf, name, kind);
 | 
				
			||||||
 | 
								if (ret > 0) {
 | 
				
			||||||
 | 
									int btf_obj_fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									btf_obj_fd = __btf_new_fd(mod_btf);
 | 
				
			||||||
 | 
									if (btf_obj_fd < 0) {
 | 
				
			||||||
 | 
										btf_put(mod_btf);
 | 
				
			||||||
 | 
										return btf_obj_fd;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return ret | (((u64)btf_obj_fd) << 32);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								spin_lock_bh(&btf_idr_lock);
 | 
				
			||||||
 | 
								btf_put(mod_btf);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							spin_unlock_bh(&btf_idr_lock);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct bpf_func_proto bpf_btf_find_by_name_kind_proto = {
 | 
				
			||||||
 | 
						.func		= bpf_btf_find_by_name_kind,
 | 
				
			||||||
 | 
						.gpl_only	= false,
 | 
				
			||||||
 | 
						.ret_type	= RET_INTEGER,
 | 
				
			||||||
 | 
						.arg1_type	= ARG_PTR_TO_MEM,
 | 
				
			||||||
 | 
						.arg2_type	= ARG_CONST_SIZE,
 | 
				
			||||||
 | 
						.arg3_type	= ARG_ANYTHING,
 | 
				
			||||||
 | 
						.arg4_type	= ARG_ANYTHING,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4584,6 +4584,8 @@ syscall_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 | 
				
			||||||
	switch (func_id) {
 | 
						switch (func_id) {
 | 
				
			||||||
	case BPF_FUNC_sys_bpf:
 | 
						case BPF_FUNC_sys_bpf:
 | 
				
			||||||
		return &bpf_sys_bpf_proto;
 | 
							return &bpf_sys_bpf_proto;
 | 
				
			||||||
 | 
						case BPF_FUNC_btf_find_by_name_kind:
 | 
				
			||||||
 | 
							return &bpf_btf_find_by_name_kind_proto;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return tracing_prog_func_proto(func_id, prog);
 | 
							return tracing_prog_func_proto(func_id, prog);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4748,6 +4748,12 @@ union bpf_attr {
 | 
				
			||||||
 * 		Execute bpf syscall with given arguments.
 | 
					 * 		Execute bpf syscall with given arguments.
 | 
				
			||||||
 * 	Return
 | 
					 * 	Return
 | 
				
			||||||
 * 		A syscall result.
 | 
					 * 		A syscall result.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * long bpf_btf_find_by_name_kind(char *name, int name_sz, u32 kind, int flags)
 | 
				
			||||||
 | 
					 * 	Description
 | 
				
			||||||
 | 
					 * 		Find BTF type with given name and kind in vmlinux BTF or in module's BTFs.
 | 
				
			||||||
 | 
					 * 	Return
 | 
				
			||||||
 | 
					 * 		Returns btf_id and btf_obj_fd in lower and upper 32 bits.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define __BPF_FUNC_MAPPER(FN)		\
 | 
					#define __BPF_FUNC_MAPPER(FN)		\
 | 
				
			||||||
	FN(unspec),			\
 | 
						FN(unspec),			\
 | 
				
			||||||
| 
						 | 
					@ -4917,6 +4923,7 @@ union bpf_attr {
 | 
				
			||||||
	FN(for_each_map_elem),		\
 | 
						FN(for_each_map_elem),		\
 | 
				
			||||||
	FN(snprintf),			\
 | 
						FN(snprintf),			\
 | 
				
			||||||
	FN(sys_bpf),			\
 | 
						FN(sys_bpf),			\
 | 
				
			||||||
 | 
						FN(btf_find_by_name_kind),	\
 | 
				
			||||||
	/* */
 | 
						/* */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
 | 
					/* integer value in 'imm' field of BPF_CALL instruction selects which helper
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue