Merge tag '5.15-rc-ksmbd-part2' of git://git.samba.org/ksmbd
[linux-2.6-microblaze.git] / kernel / bpf / btf.c
index cb4b729..dfe61df 100644 (file)
@@ -3046,43 +3046,92 @@ static void btf_struct_log(struct btf_verifier_env *env,
        btf_verifier_log(env, "size=%u vlen=%u", t->size, btf_type_vlen(t));
 }
 
-/* find 'struct bpf_spin_lock' in map value.
- * return >= 0 offset if found
- * and < 0 in case of error
- */
-int btf_find_spin_lock(const struct btf *btf, const struct btf_type *t)
+static int btf_find_struct_field(const struct btf *btf, const struct btf_type *t,
+                                const char *name, int sz, int align)
 {
        const struct btf_member *member;
        u32 i, off = -ENOENT;
 
-       if (!__btf_type_is_struct(t))
-               return -EINVAL;
-
        for_each_member(i, t, member) {
                const struct btf_type *member_type = btf_type_by_id(btf,
                                                                    member->type);
                if (!__btf_type_is_struct(member_type))
                        continue;
-               if (member_type->size != sizeof(struct bpf_spin_lock))
+               if (member_type->size != sz)
                        continue;
-               if (strcmp(__btf_name_by_offset(btf, member_type->name_off),
-                          "bpf_spin_lock"))
+               if (strcmp(__btf_name_by_offset(btf, member_type->name_off), name))
                        continue;
                if (off != -ENOENT)
-                       /* only one 'struct bpf_spin_lock' is allowed */
+                       /* only one such field is allowed */
                        return -E2BIG;
                off = btf_member_bit_offset(t, member);
                if (off % 8)
                        /* valid C code cannot generate such BTF */
                        return -EINVAL;
                off /= 8;
-               if (off % __alignof__(struct bpf_spin_lock))
-                       /* valid struct bpf_spin_lock will be 4 byte aligned */
+               if (off % align)
+                       return -EINVAL;
+       }
+       return off;
+}
+
+static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
+                               const char *name, int sz, int align)
+{
+       const struct btf_var_secinfo *vsi;
+       u32 i, off = -ENOENT;
+
+       for_each_vsi(i, t, vsi) {
+               const struct btf_type *var = btf_type_by_id(btf, vsi->type);
+               const struct btf_type *var_type = btf_type_by_id(btf, var->type);
+
+               if (!__btf_type_is_struct(var_type))
+                       continue;
+               if (var_type->size != sz)
+                       continue;
+               if (vsi->size != sz)
+                       continue;
+               if (strcmp(__btf_name_by_offset(btf, var_type->name_off), name))
+                       continue;
+               if (off != -ENOENT)
+                       /* only one such field is allowed */
+                       return -E2BIG;
+               off = vsi->offset;
+               if (off % align)
                        return -EINVAL;
        }
        return off;
 }
 
+static int btf_find_field(const struct btf *btf, const struct btf_type *t,
+                         const char *name, int sz, int align)
+{
+
+       if (__btf_type_is_struct(t))
+               return btf_find_struct_field(btf, t, name, sz, align);
+       else if (btf_type_is_datasec(t))
+               return btf_find_datasec_var(btf, t, name, sz, align);
+       return -EINVAL;
+}
+
+/* find 'struct bpf_spin_lock' in map value.
+ * return >= 0 offset if found
+ * and < 0 in case of error
+ */
+int btf_find_spin_lock(const struct btf *btf, const struct btf_type *t)
+{
+       return btf_find_field(btf, t, "bpf_spin_lock",
+                             sizeof(struct bpf_spin_lock),
+                             __alignof__(struct bpf_spin_lock));
+}
+
+int btf_find_timer(const struct btf *btf, const struct btf_type *t)
+{
+       return btf_find_field(btf, t, "bpf_timer",
+                             sizeof(struct bpf_timer),
+                             __alignof__(struct bpf_timer));
+}
+
 static void __btf_struct_show(const struct btf *btf, const struct btf_type *t,
                              u32 type_id, void *data, u8 bits_offset,
                              struct btf_show *show)
@@ -4776,6 +4825,11 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
                const struct bpf_ctx_arg_aux *ctx_arg_info = &prog->aux->ctx_arg_info[i];
 
                if (ctx_arg_info->offset == off) {
+                       if (!ctx_arg_info->btf_id) {
+                               bpf_log(log,"invalid btf_id for context argument offset %u\n", off);
+                               return false;
+                       }
+
                        info->reg_type = ctx_arg_info->reg_type;
                        info->btf = btf_vmlinux;
                        info->btf_id = ctx_arg_info->btf_id;
@@ -6159,3 +6213,5 @@ const struct bpf_func_proto bpf_btf_find_by_name_kind_proto = {
        .arg3_type      = ARG_ANYTHING,
        .arg4_type      = ARG_ANYTHING,
 };
+
+BTF_ID_LIST_GLOBAL_SINGLE(btf_task_struct_ids, struct, task_struct)