diff options
| author | Yonghong Song <yhs@fb.com> | 2021-11-11 17:26:09 -0800 | 
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2021-11-11 17:41:11 -0800 | 
| commit | 8c42d2fa4eeab6c37a0b1b1aa7a2715248ef4f34 (patch) | |
| tree | c119fc05841e8bdd8667e34b4536e76d8253d727 | |
| parent | 2326ff8d5c6628e581c87f37a8f6db1db7dc00ee (diff) | |
bpf: Support BTF_KIND_TYPE_TAG for btf_type_tag attributes
LLVM patches ([1] for clang, [2] and [3] for BPF backend)
added support for btf_type_tag attributes. This patch
added support for the kernel.
The main motivation for btf_type_tag is to bring kernel
annotations __user, __rcu etc. to btf. With such information
available in btf, bpf verifier can detect mis-usages
and reject the program. For example, for __user tagged pointer,
developers can then use proper helper like bpf_probe_read_user()
etc. to read the data.
BTF_KIND_TYPE_TAG may also useful for other tracing
facility where instead of to require user to specify
kernel/user address type, the kernel can detect it
by itself with btf.
  [1] https://reviews.llvm.org/D111199
  [2] https://reviews.llvm.org/D113222
  [3] https://reviews.llvm.org/D113496
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211112012609.1505032-1-yhs@fb.com
| -rw-r--r-- | include/uapi/linux/btf.h | 3 | ||||
| -rw-r--r-- | kernel/bpf/btf.c | 14 | ||||
| -rw-r--r-- | tools/include/uapi/linux/btf.h | 3 | 
3 files changed, 17 insertions, 3 deletions
| diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h index deb12f755f0f..b0d8fea1951d 100644 --- a/include/uapi/linux/btf.h +++ b/include/uapi/linux/btf.h @@ -43,7 +43,7 @@ struct btf_type {  	 * "size" tells the size of the type it is describing.  	 *  	 * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, -	 * FUNC, FUNC_PROTO, VAR and DECL_TAG. +	 * FUNC, FUNC_PROTO, VAR, DECL_TAG and TYPE_TAG.  	 * "type" is a type_id referring to another type.  	 */  	union { @@ -75,6 +75,7 @@ enum {  	BTF_KIND_DATASEC	= 15,	/* Section	*/  	BTF_KIND_FLOAT		= 16,	/* Floating point	*/  	BTF_KIND_DECL_TAG	= 17,	/* Decl Tag */ +	BTF_KIND_TYPE_TAG	= 18,	/* Type Tag */  	NR_BTF_KINDS,  	BTF_KIND_MAX		= NR_BTF_KINDS - 1, diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index cdb0fba65600..1dd9ba82da1e 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -282,6 +282,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {  	[BTF_KIND_DATASEC]	= "DATASEC",  	[BTF_KIND_FLOAT]	= "FLOAT",  	[BTF_KIND_DECL_TAG]	= "DECL_TAG", +	[BTF_KIND_TYPE_TAG]	= "TYPE_TAG",  };  const char *btf_type_str(const struct btf_type *t) @@ -418,6 +419,7 @@ static bool btf_type_is_modifier(const struct btf_type *t)  	case BTF_KIND_VOLATILE:  	case BTF_KIND_CONST:  	case BTF_KIND_RESTRICT: +	case BTF_KIND_TYPE_TAG:  		return true;  	} @@ -1737,6 +1739,7 @@ __btf_resolve_size(const struct btf *btf, const struct btf_type *type,  		case BTF_KIND_VOLATILE:  		case BTF_KIND_CONST:  		case BTF_KIND_RESTRICT: +		case BTF_KIND_TYPE_TAG:  			id = type->type;  			type = btf_type_by_id(btf, type->type);  			break; @@ -2345,6 +2348,8 @@ static int btf_ref_type_check_meta(struct btf_verifier_env *env,  				   const struct btf_type *t,  				   u32 meta_left)  { +	const char *value; +  	if (btf_type_vlen(t)) {  		btf_verifier_log_type(env, t, "vlen != 0");  		return -EINVAL; @@ -2360,7 +2365,7 @@ static int btf_ref_type_check_meta(struct btf_verifier_env *env,  		return -EINVAL;  	} -	/* typedef type must have a valid name, and other ref types, +	/* typedef/type_tag type must have a valid name, and other ref types,  	 * volatile, const, restrict, should have a null name.  	 */  	if (BTF_INFO_KIND(t->info) == BTF_KIND_TYPEDEF) { @@ -2369,6 +2374,12 @@ static int btf_ref_type_check_meta(struct btf_verifier_env *env,  			btf_verifier_log_type(env, t, "Invalid name");  			return -EINVAL;  		} +	} else if (BTF_INFO_KIND(t->info) == BTF_KIND_TYPE_TAG) { +		value = btf_name_by_offset(env->btf, t->name_off); +		if (!value || !value[0]) { +			btf_verifier_log_type(env, t, "Invalid name"); +			return -EINVAL; +		}  	} else {  		if (t->name_off) {  			btf_verifier_log_type(env, t, "Invalid name"); @@ -4059,6 +4070,7 @@ static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS] = {  	[BTF_KIND_DATASEC] = &datasec_ops,  	[BTF_KIND_FLOAT] = &float_ops,  	[BTF_KIND_DECL_TAG] = &decl_tag_ops, +	[BTF_KIND_TYPE_TAG] = &modifier_ops,  };  static s32 btf_check_meta(struct btf_verifier_env *env, diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h index deb12f755f0f..b0d8fea1951d 100644 --- a/tools/include/uapi/linux/btf.h +++ b/tools/include/uapi/linux/btf.h @@ -43,7 +43,7 @@ struct btf_type {  	 * "size" tells the size of the type it is describing.  	 *  	 * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, -	 * FUNC, FUNC_PROTO, VAR and DECL_TAG. +	 * FUNC, FUNC_PROTO, VAR, DECL_TAG and TYPE_TAG.  	 * "type" is a type_id referring to another type.  	 */  	union { @@ -75,6 +75,7 @@ enum {  	BTF_KIND_DATASEC	= 15,	/* Section	*/  	BTF_KIND_FLOAT		= 16,	/* Floating point	*/  	BTF_KIND_DECL_TAG	= 17,	/* Decl Tag */ +	BTF_KIND_TYPE_TAG	= 18,	/* Type Tag */  	NR_BTF_KINDS,  	BTF_KIND_MAX		= NR_BTF_KINDS - 1, | 
