Re: [PATCH bpf-next v7 09/26] bpf: Recognize lock and list fields in allocated objects

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
> 



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux