提交 f0dce1d9 编写于 作者: S Stanislav Fomichev 提交者: Daniel Borkmann

bpf: Use kvmalloc for map values in syscall

Use kvmalloc/kvfree for temporary value when manipulating a map via
syscall. kmalloc might not be sufficient for percpu maps where the value
is big (and further multiplied by hundreds of CPUs).

Can be reproduced with netcnt test on qemu with "-smp 255".
Signed-off-by: NStanislav Fomichev <sdf@google.com>
Signed-off-by: NDaniel Borkmann <daniel@iogearbox.net>
Acked-by: NSong Liu <songliubraving@fb.com>
Link: https://lore.kernel.org/bpf/20210818235216.1159202-1-sdf@google.com
上级 3666b167
......@@ -1076,7 +1076,7 @@ static int map_lookup_elem(union bpf_attr *attr)
value_size = bpf_map_value_size(map);
err = -ENOMEM;
value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
if (!value)
goto free_key;
......@@ -1091,7 +1091,7 @@ static int map_lookup_elem(union bpf_attr *attr)
err = 0;
free_value:
kfree(value);
kvfree(value);
free_key:
kfree(key);
err_put:
......@@ -1137,16 +1137,10 @@ static int map_update_elem(union bpf_attr *attr, bpfptr_t uattr)
goto err_put;
}
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
value_size = round_up(map->value_size, 8) * num_possible_cpus();
else
value_size = map->value_size;
value_size = bpf_map_value_size(map);
err = -ENOMEM;
value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
if (!value)
goto free_key;
......@@ -1157,7 +1151,7 @@ static int map_update_elem(union bpf_attr *attr, bpfptr_t uattr)
err = bpf_map_update_value(map, f, key, value, attr->flags);
free_value:
kfree(value);
kvfree(value);
free_key:
kfree(key);
err_put:
......@@ -1367,7 +1361,7 @@ int generic_map_update_batch(struct bpf_map *map,
if (!key)
return -ENOMEM;
value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
if (!value) {
kfree(key);
return -ENOMEM;
......@@ -1390,7 +1384,7 @@ int generic_map_update_batch(struct bpf_map *map,
if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp)))
err = -EFAULT;
kfree(value);
kvfree(value);
kfree(key);
return err;
}
......@@ -1429,7 +1423,7 @@ int generic_map_lookup_batch(struct bpf_map *map,
if (!buf_prevkey)
return -ENOMEM;
buf = kmalloc(map->key_size + value_size, GFP_USER | __GFP_NOWARN);
buf = kvmalloc(map->key_size + value_size, GFP_USER | __GFP_NOWARN);
if (!buf) {
kfree(buf_prevkey);
return -ENOMEM;
......@@ -1492,7 +1486,7 @@ int generic_map_lookup_batch(struct bpf_map *map,
free_buf:
kfree(buf_prevkey);
kfree(buf);
kvfree(buf);
return err;
}
......@@ -1547,7 +1541,7 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
value_size = bpf_map_value_size(map);
err = -ENOMEM;
value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
if (!value)
goto free_key;
......@@ -1579,7 +1573,7 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
err = 0;
free_value:
kfree(value);
kvfree(value);
free_key:
kfree(key);
err_put:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册