diff options
Diffstat (limited to 'kernel/bpf/arraymap.c')
| -rw-r--r-- | kernel/bpf/arraymap.c | 23 | 
1 files changed, 16 insertions, 7 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 25632a75d630..c72e0d8e1e65 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -253,8 +253,9 @@ static int array_map_update_elem(struct bpf_map *map, void *key, void *value,  {  	struct bpf_array *array = container_of(map, struct bpf_array, map);  	u32 index = *(u32 *)key; +	char *val; -	if (unlikely(map_flags > BPF_EXIST)) +	if (unlikely((map_flags & ~BPF_F_LOCK) > BPF_EXIST))  		/* unknown flags */  		return -EINVAL; @@ -262,17 +263,25 @@ static int array_map_update_elem(struct bpf_map *map, void *key, void *value,  		/* all elements were pre-allocated, cannot insert a new one */  		return -E2BIG; -	if (unlikely(map_flags == BPF_NOEXIST)) +	if (unlikely(map_flags & BPF_NOEXIST))  		/* all elements already exist */  		return -EEXIST; -	if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY) +	if (unlikely((map_flags & BPF_F_LOCK) && +		     !map_value_has_spin_lock(map))) +		return -EINVAL; + +	if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {  		memcpy(this_cpu_ptr(array->pptrs[index & array->index_mask]),  		       value, map->value_size); -	else -		memcpy(array->value + -		       array->elem_size * (index & array->index_mask), -		       value, map->value_size); +	} else { +		val = array->value + +			array->elem_size * (index & array->index_mask); +		if (map_flags & BPF_F_LOCK) +			copy_map_value_locked(map, val, value, false); +		else +			copy_map_value(map, val, value); +	}  	return 0;  }  | 
