On Tue, Nov 15, 2022 at 12:45:30AM +0530, Kumar Kartikeya Dwivedi wrote: > + parse: > + if (!tab) { > + tab = kzalloc(offsetof(struct btf_struct_metas, types[1]), > + GFP_KERNEL | __GFP_NOWARN); > + if (!tab) > + return ERR_PTR(-ENOMEM); > + } else { > + struct btf_struct_metas *new_tab; > + > + new_tab = krealloc(tab, offsetof(struct btf_struct_metas, types[tab->cnt + 1]), > + GFP_KERNEL | __GFP_NOWARN); > + if (!new_tab) { > + ret = -ENOMEM; > + goto free; > + } > + tab = new_tab; > + } If @p is %NULL, krealloc() behaves exactly like kmalloc(). That can help to simplify above a bit? > + type = &tab->types[tab->cnt]; > + > + type->btf_id = i; > + record = btf_parse_fields(btf, t, BPF_SPIN_LOCK | BPF_LIST_HEAD | BPF_LIST_NODE, t->size); > + if (IS_ERR_OR_NULL(record)) { > + ret = PTR_ERR_OR_ZERO(record) ?: -EFAULT; > + goto free; > + } > + foffs = btf_parse_field_offs(record); > + if (WARN_ON_ONCE(IS_ERR_OR_NULL(foffs))) { WARN_ON_ONCE ? Pls add a comment. > + btf_record_free(record); > + ret = -EFAULT; > + goto free; > + } > + type->record = record; > + type->field_offs = foffs; > + tab->cnt++; > + } > + return tab; > +free: > + btf_struct_metas_free(tab); > + return ERR_PTR(ret); > +} > + > +struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id) > +{ > + struct btf_struct_metas *tab; > + > + BUILD_BUG_ON(offsetof(struct btf_struct_meta, btf_id) != 0); > + tab = btf->struct_meta_tab; > + if (!tab) > + return NULL; > + return bsearch(&btf_id, tab->types, tab->cnt, sizeof(tab->types[0]), btf_id_cmp_func); > +} > + > static int btf_check_type_tags(struct btf_verifier_env *env, > struct btf *btf, int start_id) > { > @@ -5191,6 +5338,7 @@ static int btf_check_type_tags(struct btf_verifier_env *env, > static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size, > u32 log_level, char __user *log_ubuf, u32 log_size) > { > + struct btf_struct_metas *struct_meta_tab; > struct btf_verifier_env *env = NULL; > struct bpf_verifier_log *log; > struct btf *btf = NULL; > @@ -5259,15 +5407,24 @@ static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size, > if (err) > goto errout; > > + struct_meta_tab = btf_parse_struct_metas(log, btf); > + if (IS_ERR(struct_meta_tab)) { > + err = PTR_ERR(struct_meta_tab); > + goto errout; > + } > + btf->struct_meta_tab = struct_meta_tab; > + > if (log->level && bpf_verifier_log_full(log)) { > err = -ENOSPC; > - goto errout; > + goto errout_meta; > } > > btf_verifier_env_free(env); > refcount_set(&btf->refcnt, 1); > return btf; > > +errout_meta: > + btf_free_struct_meta_tab(btf); > errout: > btf_verifier_env_free(env); > if (btf) > @@ -6028,6 +6185,28 @@ int btf_struct_access(struct bpf_verifier_log *log, > u32 id = reg->btf_id; > int err; > > + while (type_is_alloc(reg->type)) { > + struct btf_struct_meta *meta; > + struct btf_record *rec; > + int i; > + > + meta = btf_find_struct_meta(btf, id); > + if (!meta) > + break; > + rec = meta->record; > + for (i = 0; i < rec->cnt; i++) { > + struct btf_field *field = &rec->fields[i]; > + u32 offset = field->offset; > + if (off < offset + btf_field_type_size(field->type) && offset < off + size) { > + bpf_log(log, > + "direct access to %s is disallowed\n", > + btf_field_type_name(field->type)); > + return -EACCES; > + } > + } > + break; > + } > + > t = btf_type_by_id(btf, id); > do { > err = btf_struct_walk(log, btf, t, off, size, &id, &tmp_flag); > @@ -7269,23 +7448,6 @@ bool btf_is_module(const struct btf *btf) > return btf->kernel_btf && strcmp(btf->name, "vmlinux") != 0; > } > > -static int btf_id_cmp_func(const void *a, const void *b) > -{ > - const int *pa = a, *pb = b; > - > - return *pa - *pb; > -} > - > -bool btf_id_set_contains(const struct btf_id_set *set, u32 id) > -{ > - return bsearch(&id, set->ids, set->cnt, sizeof(u32), btf_id_cmp_func) != NULL; > -} > - > -static void *btf_id_set8_contains(const struct btf_id_set8 *set, u32 id) > -{ > - return bsearch(&id, set->pairs, set->cnt, sizeof(set->pairs[0]), btf_id_cmp_func); > -} > - > enum { > BTF_MODULE_F_LIVE = (1 << 0), > }; > diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c > index fdbae52f463f..c96039a4e57f 100644 > --- a/kernel/bpf/syscall.c > +++ b/kernel/bpf/syscall.c > @@ -537,6 +537,7 @@ void btf_record_free(struct btf_record *rec) > btf_put(rec->fields[i].kptr.btf); > break; > case BPF_LIST_HEAD: > + case BPF_LIST_NODE: > /* Nothing to release for bpf_list_head */ > break; > default: > @@ -582,6 +583,7 @@ struct btf_record *btf_record_dup(const struct btf_record *rec) > } > break; > case BPF_LIST_HEAD: > + case BPF_LIST_NODE: > /* Nothing to acquire for bpf_list_head */ > break; > default: > @@ -648,6 +650,8 @@ void bpf_obj_free_fields(const struct btf_record *rec, void *obj) > continue; > bpf_list_head_free(field, field_ptr, obj + rec->spin_lock_off); > break; > + case BPF_LIST_NODE: > + break; > default: > WARN_ON_ONCE(1); > continue; > -- > 2.38.1 >