diff options
Diffstat (limited to 'kernel/bpf')
| -rw-r--r-- | kernel/bpf/core.c | 2 | ||||
| -rw-r--r-- | kernel/bpf/syscall.c | 25 | 
2 files changed, 18 insertions, 9 deletions
| diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index d6594e457a25..a64e7a207d2b 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -163,7 +163,7 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,  void bpf_jit_binary_free(struct bpf_binary_header *hdr)  { -	module_free(NULL, hdr); +	module_memfree(hdr);  }  #endif /* CONFIG_BPF_JIT */ diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 088ac0b1b106..536edc2be307 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -150,7 +150,7 @@ static int map_lookup_elem(union bpf_attr *attr)  	int ufd = attr->map_fd;  	struct fd f = fdget(ufd);  	struct bpf_map *map; -	void *key, *value; +	void *key, *value, *ptr;  	int err;  	if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) @@ -169,20 +169,29 @@ static int map_lookup_elem(union bpf_attr *attr)  	if (copy_from_user(key, ukey, map->key_size) != 0)  		goto free_key; -	err = -ENOENT; -	rcu_read_lock(); -	value = map->ops->map_lookup_elem(map, key); +	err = -ENOMEM; +	value = kmalloc(map->value_size, GFP_USER);  	if (!value) -		goto err_unlock; +		goto free_key; + +	rcu_read_lock(); +	ptr = map->ops->map_lookup_elem(map, key); +	if (ptr) +		memcpy(value, ptr, map->value_size); +	rcu_read_unlock(); + +	err = -ENOENT; +	if (!ptr) +		goto free_value;  	err = -EFAULT;  	if (copy_to_user(uvalue, value, map->value_size) != 0) -		goto err_unlock; +		goto free_value;  	err = 0; -err_unlock: -	rcu_read_unlock(); +free_value: +	kfree(value);  free_key:  	kfree(key);  err_put: |