mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +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 int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr);
|
||||||
static void vsock_sk_destruct(struct sock *sk);
|
static void vsock_sk_destruct(struct sock *sk);
|
||||||
static int vsock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
|
static int vsock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
|
||||||
|
static void vsock_close(struct sock *sk, long timeout);
|
||||||
|
|
||||||
/* Protocol family. */
|
/* Protocol family. */
|
||||||
struct proto vsock_proto = {
|
struct proto vsock_proto = {
|
||||||
.name = "AF_VSOCK",
|
.name = "AF_VSOCK",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.obj_size = sizeof(struct vsock_sock),
|
.obj_size = sizeof(struct vsock_sock),
|
||||||
|
.close = vsock_close,
|
||||||
#ifdef CONFIG_BPF_SYSCALL
|
#ifdef CONFIG_BPF_SYSCALL
|
||||||
.psock_update_sk_prot = vsock_bpf_update_proto,
|
.psock_update_sk_prot = vsock_bpf_update_proto,
|
||||||
#endif
|
#endif
|
||||||
@ -797,39 +799,37 @@ static bool sock_type_connectible(u16 type)
|
|||||||
|
|
||||||
static void __vsock_release(struct sock *sk, int level)
|
static void __vsock_release(struct sock *sk, int level)
|
||||||
{
|
{
|
||||||
if (sk) {
|
struct vsock_sock *vsk;
|
||||||
struct sock *pending;
|
struct sock *pending;
|
||||||
struct vsock_sock *vsk;
|
|
||||||
|
|
||||||
vsk = vsock_sk(sk);
|
vsk = vsock_sk(sk);
|
||||||
pending = NULL; /* Compiler warning. */
|
pending = NULL; /* Compiler warning. */
|
||||||
|
|
||||||
/* When "level" is SINGLE_DEPTH_NESTING, use the nested
|
/* When "level" is SINGLE_DEPTH_NESTING, use the nested
|
||||||
* version to avoid the warning "possible recursive locking
|
* version to avoid the warning "possible recursive locking
|
||||||
* detected". When "level" is 0, lock_sock_nested(sk, level)
|
* detected". When "level" is 0, lock_sock_nested(sk, level)
|
||||||
* is the same as lock_sock(sk).
|
* is the same as lock_sock(sk).
|
||||||
*/
|
*/
|
||||||
lock_sock_nested(sk, level);
|
lock_sock_nested(sk, level);
|
||||||
|
|
||||||
if (vsk->transport)
|
if (vsk->transport)
|
||||||
vsk->transport->release(vsk);
|
vsk->transport->release(vsk);
|
||||||
else if (sock_type_connectible(sk->sk_type))
|
else if (sock_type_connectible(sk->sk_type))
|
||||||
vsock_remove_sock(vsk);
|
vsock_remove_sock(vsk);
|
||||||
|
|
||||||
sock_orphan(sk);
|
sock_orphan(sk);
|
||||||
sk->sk_shutdown = SHUTDOWN_MASK;
|
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. */
|
/* Clean up any sockets that never were accepted. */
|
||||||
while ((pending = vsock_dequeue_accept(sk)) != NULL) {
|
while ((pending = vsock_dequeue_accept(sk)) != NULL) {
|
||||||
__vsock_release(pending, SINGLE_DEPTH_NESTING);
|
__vsock_release(pending, SINGLE_DEPTH_NESTING);
|
||||||
sock_put(pending);
|
sock_put(pending);
|
||||||
}
|
|
||||||
|
|
||||||
release_sock(sk);
|
|
||||||
sock_put(sk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
release_sock(sk);
|
||||||
|
sock_put(sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vsock_sk_destruct(struct sock *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);
|
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)
|
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->sk = NULL;
|
||||||
sock->state = SS_FREE;
|
sock->state = SS_FREE;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user