OSDN Git Service

bpf: Support BTF_KIND_TYPE_TAG for btf_type_tag attributes
authorYonghong Song <yhs@fb.com>
Fri, 12 Nov 2021 01:26:09 +0000 (17:26 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 12 Nov 2021 01:41:11 +0000 (17:41 -0800)
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
include/uapi/linux/btf.h
kernel/bpf/btf.c
tools/include/uapi/linux/btf.h

index deb12f7..b0d8fea 100644 (file)
@@ -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,
index cdb0fba..1dd9ba8 100644 (file)
@@ -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,
index deb12f7..b0d8fea 100644 (file)
@@ -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,