return 0;
 }
 
+static int btf_check_type_tags(struct btf_verifier_env *env,
+                              struct btf *btf, int start_id)
+{
+       int i, n, good_id = start_id - 1;
+       bool in_tags;
+
+       n = btf_nr_types(btf);
+       for (i = start_id; i < n; i++) {
+               const struct btf_type *t;
+               u32 cur_id = i;
+
+               t = btf_type_by_id(btf, i);
+               if (!t)
+                       return -EINVAL;
+               if (!btf_type_is_modifier(t))
+                       continue;
+
+               cond_resched();
+
+               in_tags = btf_type_is_type_tag(t);
+               while (btf_type_is_modifier(t)) {
+                       if (btf_type_is_type_tag(t)) {
+                               if (!in_tags) {
+                                       btf_verifier_log(env, "Type tags don't precede modifiers");
+                                       return -EINVAL;
+                               }
+                       } else if (in_tags) {
+                               in_tags = false;
+                       }
+                       if (cur_id <= good_id)
+                               break;
+                       /* Move to next type */
+                       cur_id = t->type;
+                       t = btf_type_by_id(btf, cur_id);
+                       if (!t)
+                               return -EINVAL;
+               }
+               good_id = i;
+       }
+       return 0;
+}
+
 static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size,
                             u32 log_level, char __user *log_ubuf, u32 log_size)
 {
        if (err)
                goto errout;
 
+       err = btf_check_type_tags(env, btf, 1);
+       if (err)
+               goto errout;
+
        if (log->level && bpf_verifier_log_full(log)) {
                err = -ENOSPC;
                goto errout;
        if (err)
                goto errout;
 
+       err = btf_check_type_tags(env, btf, 1);
+       if (err)
+               goto errout;
+
        /* btf_parse_vmlinux() runs under bpf_verifier_lock */
        bpf_ctx_convert.t = btf_type_by_id(btf, bpf_ctx_convert_btf_id[0]);
 
        if (err)
                goto errout;
 
+       err = btf_check_type_tags(env, btf, btf_nr_types(base_btf));
+       if (err)
+               goto errout;
+
        btf_verifier_env_free(env);
        refcount_set(&btf->refcnt, 1);
        return btf;