Skip to content

Commit

Permalink
bpf, vsock: Invoke proto::close on close()
Browse files Browse the repository at this point in the history
vsock defines a BPF callback to be invoked when close() is called. However,
this callback is never actually executed. As a result, a closed vsock
socket is not automatically removed from the sockmap/sockhash.

Introduce a dummy vsock_close() and make vsock_release() call proto::close.

Note: changes in __vsock_release() look messy, but it's only due to indent
level reduction and variables xmas tree reorder.

Fixes: 634f1a7 ("vsock: support sockmap")
Signed-off-by: Michal Luczaj <mhal@rbox.co>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Luigi Leonardi <leonardi@redhat.com>
Link: https://lore.kernel.org/r/20241118-vsock-bpf-poll-close-v1-3-f1b9669cacdc@rbox.co
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
  • Loading branch information
mmhal authored and klarasm committed Dec 3, 2024
1 parent ed7ce7f commit d780b3d
Showing 1 changed file with 40 additions and 27 deletions.
67 changes: 40 additions & 27 deletions net/vmw_vsock/af_vsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,14 @@
static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr);
static void vsock_sk_destruct(struct sock *sk);
static int vsock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
static void vsock_close(struct sock *sk, long timeout);

/* Protocol family. */
struct proto vsock_proto = {
.name = "AF_VSOCK",
.owner = THIS_MODULE,
.obj_size = sizeof(struct vsock_sock),
.close = vsock_close,
#ifdef CONFIG_BPF_SYSCALL
.psock_update_sk_prot = vsock_bpf_update_proto,
#endif
Expand Down Expand Up @@ -797,39 +799,37 @@ static bool sock_type_connectible(u16 type)

static void __vsock_release(struct sock *sk, int level)
{
if (sk) {
struct sock *pending;
struct vsock_sock *vsk;

vsk = vsock_sk(sk);
pending = NULL; /* Compiler warning. */
struct vsock_sock *vsk;
struct sock *pending;

/* When "level" is SINGLE_DEPTH_NESTING, use the nested
* version to avoid the warning "possible recursive locking
* detected". When "level" is 0, lock_sock_nested(sk, level)
* is the same as lock_sock(sk).
*/
lock_sock_nested(sk, level);
vsk = vsock_sk(sk);
pending = NULL; /* Compiler warning. */

if (vsk->transport)
vsk->transport->release(vsk);
else if (sock_type_connectible(sk->sk_type))
vsock_remove_sock(vsk);
/* When "level" is SINGLE_DEPTH_NESTING, use the nested
* version to avoid the warning "possible recursive locking
* detected". When "level" is 0, lock_sock_nested(sk, level)
* is the same as lock_sock(sk).
*/
lock_sock_nested(sk, level);

sock_orphan(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
if (vsk->transport)
vsk->transport->release(vsk);
else if (sock_type_connectible(sk->sk_type))
vsock_remove_sock(vsk);

skb_queue_purge(&sk->sk_receive_queue);
sock_orphan(sk);
sk->sk_shutdown = SHUTDOWN_MASK;

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

release_sock(sk);
sock_put(sk);
/* Clean up any sockets that never were accepted. */
while ((pending = vsock_dequeue_accept(sk)) != NULL) {
__vsock_release(pending, SINGLE_DEPTH_NESTING);
sock_put(pending);
}

release_sock(sk);
sock_put(sk);
}

static void vsock_sk_destruct(struct sock *sk)
Expand Down Expand Up @@ -901,9 +901,22 @@ void vsock_data_ready(struct sock *sk)
}
EXPORT_SYMBOL_GPL(vsock_data_ready);

/* Dummy callback required by sockmap.
* See unconditional call of saved_close() in sock_map_close().
*/
static void vsock_close(struct sock *sk, long timeout)
{
}

static int vsock_release(struct socket *sock)
{
__vsock_release(sock->sk, 0);
struct sock *sk = sock->sk;

if (!sk)
return 0;

sk->sk_prot->close(sk, 0);
__vsock_release(sk, 0);
sock->sk = NULL;
sock->state = SS_FREE;

Expand Down

0 comments on commit d780b3d

Please sign in to comment.