Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Acquire map uref in .init_seq_private for sock{map,hash} iterator

sock_map_iter_attach_target() acquires a map uref, and the uref may be
released before or in the middle of iterating map elements. For example,
the uref could be released in sock_map_iter_detach_target() as part of
bpf_link_release(), or could be released in bpf_map_put_with_uref() as
part of bpf_map_release().

Fixing it by acquiring an extra map uref in .init_seq_private and
releasing it in .fini_seq_private.

Fixes: 0365351524d7 ("net: Allow iterating sockmap and sockhash")
Signed-off-by: Hou Tao <houtao1@huawei.com>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/r/20220810080538.1845898-5-houtao@huaweicloud.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Hou Tao and committed by
Alexei Starovoitov
f0d2b271 3c5f6e69

+19 -1
+19 -1
net/core/sock_map.c
··· 783 783 { 784 784 struct sock_map_seq_info *info = priv_data; 785 785 786 + bpf_map_inc_with_uref(aux->map); 786 787 info->map = aux->map; 787 788 return 0; 789 + } 790 + 791 + static void sock_map_fini_seq_private(void *priv_data) 792 + { 793 + struct sock_map_seq_info *info = priv_data; 794 + 795 + bpf_map_put_with_uref(info->map); 788 796 } 789 797 790 798 static const struct bpf_iter_seq_info sock_map_iter_seq_info = { 791 799 .seq_ops = &sock_map_seq_ops, 792 800 .init_seq_private = sock_map_init_seq_private, 801 + .fini_seq_private = sock_map_fini_seq_private, 793 802 .seq_priv_size = sizeof(struct sock_map_seq_info), 794 803 }; 795 804 ··· 1378 1369 }; 1379 1370 1380 1371 static int sock_hash_init_seq_private(void *priv_data, 1381 - struct bpf_iter_aux_info *aux) 1372 + struct bpf_iter_aux_info *aux) 1382 1373 { 1383 1374 struct sock_hash_seq_info *info = priv_data; 1384 1375 1376 + bpf_map_inc_with_uref(aux->map); 1385 1377 info->map = aux->map; 1386 1378 info->htab = container_of(aux->map, struct bpf_shtab, map); 1387 1379 return 0; 1388 1380 } 1389 1381 1382 + static void sock_hash_fini_seq_private(void *priv_data) 1383 + { 1384 + struct sock_hash_seq_info *info = priv_data; 1385 + 1386 + bpf_map_put_with_uref(info->map); 1387 + } 1388 + 1390 1389 static const struct bpf_iter_seq_info sock_hash_iter_seq_info = { 1391 1390 .seq_ops = &sock_hash_seq_ops, 1392 1391 .init_seq_private = sock_hash_init_seq_private, 1392 + .fini_seq_private = sock_hash_fini_seq_private, 1393 1393 .seq_priv_size = sizeof(struct sock_hash_seq_info), 1394 1394 }; 1395 1395