mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 01:05:29 +00:00
bpf, vsock: Invoke proto::close on close()
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: 634f1a7110
("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>
This commit is contained in:
parent
9c2a2a4513
commit
135ffc7bec
@ -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
|
||||
@ -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;
|
||||
struct vsock_sock *vsk;
|
||||
struct sock *pending;
|
||||
|
||||
vsk = vsock_sk(sk);
|
||||
pending = NULL; /* Compiler warning. */
|
||||
vsk = vsock_sk(sk);
|
||||
pending = NULL; /* Compiler warning. */
|
||||
|
||||
/* 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);
|
||||
/* 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);
|
||||
|
||||
if (vsk->transport)
|
||||
vsk->transport->release(vsk);
|
||||
else if (sock_type_connectible(sk->sk_type))
|
||||
vsock_remove_sock(vsk);
|
||||
if (vsk->transport)
|
||||
vsk->transport->release(vsk);
|
||||
else if (sock_type_connectible(sk->sk_type))
|
||||
vsock_remove_sock(vsk);
|
||||
|
||||
sock_orphan(sk);
|
||||
sk->sk_shutdown = SHUTDOWN_MASK;
|
||||
sock_orphan(sk);
|
||||
sk->sk_shutdown = SHUTDOWN_MASK;
|
||||
|
||||
skb_queue_purge(&sk->sk_receive_queue);
|
||||
skb_queue_purge(&sk->sk_receive_queue);
|
||||
|
||||
/* 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);
|
||||
/* 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)
|
||||
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user