Skip to content

Commit 20a39ea

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf-vsock-fix-poll-and-close'
Michal Luczaj says: ==================== bpf, vsock: Fix poll() and close() Two small fixes for vsock: poll() missing a queue check, and close() not invoking sockmap cleanup. Signed-off-by: Michal Luczaj <[email protected]> Acked-by: John Fastabend <[email protected]> --- ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 8618f5f + 5157454 commit 20a39ea

File tree

2 files changed

+120
-27
lines changed

2 files changed

+120
-27
lines changed

net/vmw_vsock/af_vsock.c

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,14 @@
117117
static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr);
118118
static void vsock_sk_destruct(struct sock *sk);
119119
static int vsock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
120+
static void vsock_close(struct sock *sk, long timeout);
120121

121122
/* Protocol family. */
122123
struct proto vsock_proto = {
123124
.name = "AF_VSOCK",
124125
.owner = THIS_MODULE,
125126
.obj_size = sizeof(struct vsock_sock),
127+
.close = vsock_close,
126128
#ifdef CONFIG_BPF_SYSCALL
127129
.psock_update_sk_prot = vsock_bpf_update_proto,
128130
#endif
@@ -797,39 +799,37 @@ static bool sock_type_connectible(u16 type)
797799

798800
static void __vsock_release(struct sock *sk, int level)
799801
{
800-
if (sk) {
801-
struct sock *pending;
802-
struct vsock_sock *vsk;
803-
804-
vsk = vsock_sk(sk);
805-
pending = NULL; /* Compiler warning. */
802+
struct vsock_sock *vsk;
803+
struct sock *pending;
806804

807-
/* When "level" is SINGLE_DEPTH_NESTING, use the nested
808-
* version to avoid the warning "possible recursive locking
809-
* detected". When "level" is 0, lock_sock_nested(sk, level)
810-
* is the same as lock_sock(sk).
811-
*/
812-
lock_sock_nested(sk, level);
805+
vsk = vsock_sk(sk);
806+
pending = NULL; /* Compiler warning. */
813807

814-
if (vsk->transport)
815-
vsk->transport->release(vsk);
816-
else if (sock_type_connectible(sk->sk_type))
817-
vsock_remove_sock(vsk);
808+
/* When "level" is SINGLE_DEPTH_NESTING, use the nested
809+
* version to avoid the warning "possible recursive locking
810+
* detected". When "level" is 0, lock_sock_nested(sk, level)
811+
* is the same as lock_sock(sk).
812+
*/
813+
lock_sock_nested(sk, level);
818814

819-
sock_orphan(sk);
820-
sk->sk_shutdown = SHUTDOWN_MASK;
815+
if (vsk->transport)
816+
vsk->transport->release(vsk);
817+
else if (sock_type_connectible(sk->sk_type))
818+
vsock_remove_sock(vsk);
821819

822-
skb_queue_purge(&sk->sk_receive_queue);
820+
sock_orphan(sk);
821+
sk->sk_shutdown = SHUTDOWN_MASK;
823822

824-
/* Clean up any sockets that never were accepted. */
825-
while ((pending = vsock_dequeue_accept(sk)) != NULL) {
826-
__vsock_release(pending, SINGLE_DEPTH_NESTING);
827-
sock_put(pending);
828-
}
823+
skb_queue_purge(&sk->sk_receive_queue);
829824

830-
release_sock(sk);
831-
sock_put(sk);
825+
/* Clean up any sockets that never were accepted. */
826+
while ((pending = vsock_dequeue_accept(sk)) != NULL) {
827+
__vsock_release(pending, SINGLE_DEPTH_NESTING);
828+
sock_put(pending);
832829
}
830+
831+
release_sock(sk);
832+
sock_put(sk);
833833
}
834834

835835
static void vsock_sk_destruct(struct sock *sk)
@@ -901,9 +901,22 @@ void vsock_data_ready(struct sock *sk)
901901
}
902902
EXPORT_SYMBOL_GPL(vsock_data_ready);
903903

904+
/* Dummy callback required by sockmap.
905+
* See unconditional call of saved_close() in sock_map_close().
906+
*/
907+
static void vsock_close(struct sock *sk, long timeout)
908+
{
909+
}
910+
904911
static int vsock_release(struct socket *sock)
905912
{
906-
__vsock_release(sock->sk, 0);
913+
struct sock *sk = sock->sk;
914+
915+
if (!sk)
916+
return 0;
917+
918+
sk->sk_prot->close(sk, 0);
919+
__vsock_release(sk, 0);
907920
sock->sk = NULL;
908921
sock->state = SS_FREE;
909922

@@ -1054,6 +1067,9 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
10541067
mask |= EPOLLRDHUP;
10551068
}
10561069

1070+
if (sk_is_readable(sk))
1071+
mask |= EPOLLIN | EPOLLRDNORM;
1072+
10571073
if (sock->type == SOCK_DGRAM) {
10581074
/* For datagram sockets we can read if there is something in
10591075
* the queue and write as long as the socket isn't shutdown for

tools/testing/selftests/bpf/prog_tests/sockmap_basic.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,35 @@ static void test_sockmap_create_update_free(enum bpf_map_type map_type)
108108
close(s);
109109
}
110110

111+
static void test_sockmap_vsock_delete_on_close(void)
112+
{
113+
int err, c, p, map;
114+
const int zero = 0;
115+
116+
err = create_pair(AF_VSOCK, SOCK_STREAM, &c, &p);
117+
if (!ASSERT_OK(err, "create_pair(AF_VSOCK)"))
118+
return;
119+
120+
map = bpf_map_create(BPF_MAP_TYPE_SOCKMAP, NULL, sizeof(int),
121+
sizeof(int), 1, NULL);
122+
if (!ASSERT_GE(map, 0, "bpf_map_create")) {
123+
close(c);
124+
goto out;
125+
}
126+
127+
err = bpf_map_update_elem(map, &zero, &c, BPF_NOEXIST);
128+
close(c);
129+
if (!ASSERT_OK(err, "bpf_map_update"))
130+
goto out;
131+
132+
err = bpf_map_update_elem(map, &zero, &p, BPF_NOEXIST);
133+
ASSERT_OK(err, "after close(), bpf_map_update");
134+
135+
out:
136+
close(p);
137+
close(map);
138+
}
139+
111140
static void test_skmsg_helpers(enum bpf_map_type map_type)
112141
{
113142
struct test_skmsg_load_helpers *skel;
@@ -937,12 +966,58 @@ static void test_sockmap_same_sock(void)
937966
test_sockmap_pass_prog__destroy(skel);
938967
}
939968

969+
static void test_sockmap_skb_verdict_vsock_poll(void)
970+
{
971+
struct test_sockmap_pass_prog *skel;
972+
int err, map, conn, peer;
973+
struct bpf_program *prog;
974+
struct bpf_link *link;
975+
char buf = 'x';
976+
int zero = 0;
977+
978+
skel = test_sockmap_pass_prog__open_and_load();
979+
if (!ASSERT_OK_PTR(skel, "open_and_load"))
980+
return;
981+
982+
if (create_pair(AF_VSOCK, SOCK_STREAM, &conn, &peer))
983+
goto destroy;
984+
985+
prog = skel->progs.prog_skb_verdict;
986+
map = bpf_map__fd(skel->maps.sock_map_rx);
987+
link = bpf_program__attach_sockmap(prog, map);
988+
if (!ASSERT_OK_PTR(link, "bpf_program__attach_sockmap"))
989+
goto close;
990+
991+
err = bpf_map_update_elem(map, &zero, &conn, BPF_ANY);
992+
if (!ASSERT_OK(err, "bpf_map_update_elem"))
993+
goto detach;
994+
995+
if (xsend(peer, &buf, 1, 0) != 1)
996+
goto detach;
997+
998+
err = poll_read(conn, IO_TIMEOUT_SEC);
999+
if (!ASSERT_OK(err, "poll"))
1000+
goto detach;
1001+
1002+
if (xrecv_nonblock(conn, &buf, 1, 0) != 1)
1003+
FAIL("xrecv_nonblock");
1004+
detach:
1005+
bpf_link__detach(link);
1006+
close:
1007+
xclose(conn);
1008+
xclose(peer);
1009+
destroy:
1010+
test_sockmap_pass_prog__destroy(skel);
1011+
}
1012+
9401013
void test_sockmap_basic(void)
9411014
{
9421015
if (test__start_subtest("sockmap create_update_free"))
9431016
test_sockmap_create_update_free(BPF_MAP_TYPE_SOCKMAP);
9441017
if (test__start_subtest("sockhash create_update_free"))
9451018
test_sockmap_create_update_free(BPF_MAP_TYPE_SOCKHASH);
1019+
if (test__start_subtest("sockmap vsock delete on close"))
1020+
test_sockmap_vsock_delete_on_close();
9461021
if (test__start_subtest("sockmap sk_msg load helpers"))
9471022
test_skmsg_helpers(BPF_MAP_TYPE_SOCKMAP);
9481023
if (test__start_subtest("sockhash sk_msg load helpers"))
@@ -997,4 +1072,6 @@ void test_sockmap_basic(void)
9971072
test_skmsg_helpers_with_link(BPF_MAP_TYPE_SOCKMAP);
9981073
if (test__start_subtest("sockhash sk_msg attach sockhash helpers with link"))
9991074
test_skmsg_helpers_with_link(BPF_MAP_TYPE_SOCKHASH);
1075+
if (test__start_subtest("sockmap skb_verdict vsock poll"))
1076+
test_sockmap_skb_verdict_vsock_poll();
10001077
}

0 commit comments

Comments
 (0)