diff options
Diffstat (limited to 'kernel/bpf')
| -rw-r--r-- | kernel/bpf/bpf_struct_ops.c | 14 | ||||
| -rw-r--r-- | kernel/bpf/btf.c | 2 | ||||
| -rw-r--r-- | kernel/bpf/cgroup.c | 7 | ||||
| -rw-r--r-- | kernel/bpf/syscall.c | 5 | 
4 files changed, 22 insertions, 6 deletions
| diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index 042f95534f86..68a89a9f7ccd 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -482,13 +482,21 @@ static int bpf_struct_ops_map_delete_elem(struct bpf_map *map, void *key)  	prev_state = cmpxchg(&st_map->kvalue.state,  			     BPF_STRUCT_OPS_STATE_INUSE,  			     BPF_STRUCT_OPS_STATE_TOBEFREE); -	if (prev_state == BPF_STRUCT_OPS_STATE_INUSE) { +	switch (prev_state) { +	case BPF_STRUCT_OPS_STATE_INUSE:  		st_map->st_ops->unreg(&st_map->kvalue.data);  		if (refcount_dec_and_test(&st_map->kvalue.refcnt))  			bpf_map_put(map); +		return 0; +	case BPF_STRUCT_OPS_STATE_TOBEFREE: +		return -EINPROGRESS; +	case BPF_STRUCT_OPS_STATE_INIT: +		return -ENOENT; +	default: +		WARN_ON_ONCE(1); +		/* Should never happen.  Treat it as not found. */ +		return -ENOENT;  	} - -	return 0;  }  static void bpf_struct_ops_map_seq_show_elem(struct bpf_map *map, void *key, diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 787140095e58..32ab9225026e 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -2418,7 +2418,7 @@ static int btf_enum_check_member(struct btf_verifier_env *env,  	struct_size = struct_type->size;  	bytes_offset = BITS_ROUNDDOWN_BYTES(struct_bits_off); -	if (struct_size - bytes_offset < sizeof(int)) { +	if (struct_size - bytes_offset < member_type->size) {  		btf_verifier_log_member(env, struct_type, member,  					"Member exceeds struct_size");  		return -EINVAL; diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 9a500fadbef5..4f1472409ef8 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -227,6 +227,9 @@ cleanup:  	for (i = 0; i < NR; i++)  		bpf_prog_array_free(arrays[i]); +	for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p)) +		cgroup_bpf_put(p); +  	percpu_ref_exit(&cgrp->bpf.refcnt);  	return -ENOMEM; @@ -302,8 +305,8 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,  	u32 saved_flags = (flags & (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI));  	struct list_head *progs = &cgrp->bpf.progs[type];  	struct bpf_prog *old_prog = NULL; -	struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE], -		*old_storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {NULL}; +	struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {}; +	struct bpf_cgroup_storage *old_storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {};  	struct bpf_prog_list *pl, *replace_pl = NULL;  	enum bpf_cgroup_storage_type stype;  	int err; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index a91ad518c050..0c7fb0d4836d 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1510,6 +1510,11 @@ static int map_freeze(const union bpf_attr *attr)  	if (IS_ERR(map))  		return PTR_ERR(map); +	if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS) { +		fdput(f); +		return -ENOTSUPP; +	} +  	mutex_lock(&map->freeze_mutex);  	if (map->writecnt) { | 
