Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80f09807 authored by Jorgen Hansen's avatar Jorgen Hansen Committed by Greg Kroah-Hartman
Browse files

VSOCK: Send reset control packet when socket is partially bound



[ Upstream commit a915b982d8f5e4295f64b8dd37ce753874867e88 ]

If a server side socket is bound to an address, but not in the listening
state yet, incoming connection requests should receive a reset control
packet in response. However, the function used to send the reset
silently drops the reset packet if the sending socket isn't bound
to a remote address (as is the case for a bound socket not yet in
the listening state). This change fixes this by using the src
of the incoming packet as destination for the reset packet in
this case.

Fixes: d021c344 ("VSOCK: Introduce VM Sockets")
Reviewed-by: default avatarAdit Ranadive <aditr@vmware.com>
Reviewed-by: default avatarVishnu Dasa <vdasa@vmware.com>
Signed-off-by: default avatarJorgen Hansen <jhansen@vmware.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2510d91b
Loading
Loading
Loading
Loading
+50 −17
Original line number Diff line number Diff line
@@ -265,7 +265,8 @@ vmci_transport_send_control_pkt_bh(struct sockaddr_vm *src,
}

static int
vmci_transport_send_control_pkt(struct sock *sk,
vmci_transport_alloc_send_control_pkt(struct sockaddr_vm *src,
				      struct sockaddr_vm *dst,
				      enum vmci_transport_packet_type type,
				      u64 size,
				      u64 mode,
@@ -274,23 +275,13 @@ vmci_transport_send_control_pkt(struct sock *sk,
				      struct vmci_handle handle)
{
	struct vmci_transport_packet *pkt;
	struct vsock_sock *vsk;
	int err;

	vsk = vsock_sk(sk);

	if (!vsock_addr_bound(&vsk->local_addr))
		return -EINVAL;

	if (!vsock_addr_bound(&vsk->remote_addr))
		return -EINVAL;

	pkt = kmalloc(sizeof(*pkt), GFP_KERNEL);
	if (!pkt)
		return -ENOMEM;

	err = __vmci_transport_send_control_pkt(pkt, &vsk->local_addr,
						&vsk->remote_addr, type, size,
	err = __vmci_transport_send_control_pkt(pkt, src, dst, type, size,
						mode, wait, proto, handle,
						true);
	kfree(pkt);
@@ -298,6 +289,31 @@ vmci_transport_send_control_pkt(struct sock *sk,
	return err;
}

static int
vmci_transport_send_control_pkt(struct sock *sk,
				enum vmci_transport_packet_type type,
				u64 size,
				u64 mode,
				struct vmci_transport_waiting_info *wait,
				u16 proto,
				struct vmci_handle handle)
{
	struct vsock_sock *vsk;

	vsk = vsock_sk(sk);

	if (!vsock_addr_bound(&vsk->local_addr))
		return -EINVAL;

	if (!vsock_addr_bound(&vsk->remote_addr))
		return -EINVAL;

	return vmci_transport_alloc_send_control_pkt(&vsk->local_addr,
						     &vsk->remote_addr,
						     type, size, mode,
						     wait, proto, handle);
}

static int vmci_transport_send_reset_bh(struct sockaddr_vm *dst,
					struct sockaddr_vm *src,
					struct vmci_transport_packet *pkt)
@@ -313,9 +329,26 @@ static int vmci_transport_send_reset_bh(struct sockaddr_vm *dst,
static int vmci_transport_send_reset(struct sock *sk,
				     struct vmci_transport_packet *pkt)
{
	struct sockaddr_vm *dst_ptr;
	struct sockaddr_vm dst;
	struct vsock_sock *vsk;

	if (pkt->type == VMCI_TRANSPORT_PACKET_TYPE_RST)
		return 0;
	return vmci_transport_send_control_pkt(sk,

	vsk = vsock_sk(sk);

	if (!vsock_addr_bound(&vsk->local_addr))
		return -EINVAL;

	if (vsock_addr_bound(&vsk->remote_addr)) {
		dst_ptr = &vsk->remote_addr;
	} else {
		vsock_addr_init(&dst, pkt->dg.src.context,
				pkt->src_port);
		dst_ptr = &dst;
	}
	return vmci_transport_alloc_send_control_pkt(&vsk->local_addr, dst_ptr,
					     VMCI_TRANSPORT_PACKET_TYPE_RST,
					     0, 0, NULL, VSOCK_PROTO_INVALID,
					     VMCI_INVALID_HANDLE);