bpf: Pass map file to .map_update_batch directly
authorHou Tao <houtao1@huawei.com>
Wed, 16 Nov 2022 07:50:58 +0000 (15:50 +0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Thu, 17 Nov 2022 16:12:35 +0000 (17:12 +0100)
commit3af43ba4c6019b29c048921eb8147eb010165329
tree2fea060ff4f09716ed08751bb3354da5f7f47843
parent383f1a8df8faba88a3bafaddc02f59421bad6829
bpf: Pass map file to .map_update_batch directly

Currently bpf_map_do_batch() first invokes fdget(batch.map_fd) to get
the target map file, then it invokes generic_map_update_batch() to do
batch update. generic_map_update_batch() will get the target map file
by using fdget(batch.map_fd) again and pass it to bpf_map_update_value().

The problem is map file returned by the second fdget() may be NULL or a
totally different file compared by map file in bpf_map_do_batch(). The
reason is that the first fdget() only guarantees the liveness of struct
file instead of file descriptor and the file description may be released
by concurrent close() through pick_file().

It doesn't incur any problem as for now, because maps with batch update
support don't use map file in .map_fd_get_ptr() ops. But it is better to
fix the potential access of an invalid map file.

Using __bpf_map_get() again in generic_map_update_batch() can not fix
the problem, because batch.map_fd may be closed and reopened, and the
returned map file may be different with map file got in
bpf_map_do_batch(), so just passing the map file directly to
.map_update_batch() in bpf_map_do_batch().

Signed-off-by: Hou Tao <houtao1@huawei.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20221116075059.1551277-1-houtao@huaweicloud.com
include/linux/bpf.h
kernel/bpf/syscall.c