diff options
author | Martin KaFai Lau <kafai@fb.com> | 2017-06-28 02:08:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-29 13:13:25 -0400 |
commit | 14dc6f04f49dc12614d7e90928b495b8d73cd471 (patch) | |
tree | 159ebddef04be2ae417c503ab46593be570c680f /kernel/bpf/arraymap.c | |
parent | 77b0d3617738e532bae683bf9d88ea35fff223e5 (diff) |
bpf: Add syscall lookup support for fd array and htab
This patch allows userspace to do BPF_MAP_LOOKUP_ELEM on
BPF_MAP_TYPE_PROG_ARRAY,
BPF_MAP_TYPE_ARRAY_OF_MAPS and
BPF_MAP_TYPE_HASH_OF_MAPS.
The lookup returns a prog-id or map-id to the userspace.
The userspace can then use the BPF_PROG_GET_FD_BY_ID
or BPF_MAP_GET_FD_BY_ID to get a fd.
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/bpf/arraymap.c')
-rw-r--r-- | kernel/bpf/arraymap.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index ecb43542246e..d771a3872500 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c | |||
@@ -335,6 +335,26 @@ static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key) | |||
335 | } | 335 | } |
336 | 336 | ||
337 | /* only called from syscall */ | 337 | /* only called from syscall */ |
338 | int bpf_fd_array_map_lookup_elem(struct bpf_map *map, void *key, u32 *value) | ||
339 | { | ||
340 | void **elem, *ptr; | ||
341 | int ret = 0; | ||
342 | |||
343 | if (!map->ops->map_fd_sys_lookup_elem) | ||
344 | return -ENOTSUPP; | ||
345 | |||
346 | rcu_read_lock(); | ||
347 | elem = array_map_lookup_elem(map, key); | ||
348 | if (elem && (ptr = READ_ONCE(*elem))) | ||
349 | *value = map->ops->map_fd_sys_lookup_elem(ptr); | ||
350 | else | ||
351 | ret = -ENOENT; | ||
352 | rcu_read_unlock(); | ||
353 | |||
354 | return ret; | ||
355 | } | ||
356 | |||
357 | /* only called from syscall */ | ||
338 | int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file, | 358 | int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file, |
339 | void *key, void *value, u64 map_flags) | 359 | void *key, void *value, u64 map_flags) |
340 | { | 360 | { |
@@ -400,6 +420,11 @@ static void prog_fd_array_put_ptr(void *ptr) | |||
400 | bpf_prog_put(ptr); | 420 | bpf_prog_put(ptr); |
401 | } | 421 | } |
402 | 422 | ||
423 | static u32 prog_fd_array_sys_lookup_elem(void *ptr) | ||
424 | { | ||
425 | return ((struct bpf_prog *)ptr)->aux->id; | ||
426 | } | ||
427 | |||
403 | /* decrement refcnt of all bpf_progs that are stored in this map */ | 428 | /* decrement refcnt of all bpf_progs that are stored in this map */ |
404 | void bpf_fd_array_map_clear(struct bpf_map *map) | 429 | void bpf_fd_array_map_clear(struct bpf_map *map) |
405 | { | 430 | { |
@@ -418,6 +443,7 @@ const struct bpf_map_ops prog_array_map_ops = { | |||
418 | .map_delete_elem = fd_array_map_delete_elem, | 443 | .map_delete_elem = fd_array_map_delete_elem, |
419 | .map_fd_get_ptr = prog_fd_array_get_ptr, | 444 | .map_fd_get_ptr = prog_fd_array_get_ptr, |
420 | .map_fd_put_ptr = prog_fd_array_put_ptr, | 445 | .map_fd_put_ptr = prog_fd_array_put_ptr, |
446 | .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem, | ||
421 | }; | 447 | }; |
422 | 448 | ||
423 | static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file, | 449 | static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file, |
@@ -585,4 +611,5 @@ const struct bpf_map_ops array_of_maps_map_ops = { | |||
585 | .map_delete_elem = fd_array_map_delete_elem, | 611 | .map_delete_elem = fd_array_map_delete_elem, |
586 | .map_fd_get_ptr = bpf_map_fd_get_ptr, | 612 | .map_fd_get_ptr = bpf_map_fd_get_ptr, |
587 | .map_fd_put_ptr = bpf_map_fd_put_ptr, | 613 | .map_fd_put_ptr = bpf_map_fd_put_ptr, |
614 | .map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem, | ||
588 | }; | 615 | }; |