| From foo@baz Fri Jan 4 20:27:35 CET 2019 |
| From: Jorgen Hansen <jhansen@vmware.com> |
| Date: Tue, 18 Dec 2018 00:34:06 -0800 |
| Subject: VSOCK: Send reset control packet when socket is partially bound |
| |
| From: Jorgen Hansen <jhansen@vmware.com> |
| |
| [ 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: d021c344051a ("VSOCK: Introduce VM Sockets") |
| Reviewed-by: Adit Ranadive <aditr@vmware.com> |
| Reviewed-by: Vishnu Dasa <vdasa@vmware.com> |
| Signed-off-by: Jorgen Hansen <jhansen@vmware.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/vmw_vsock/vmci_transport.c | 67 ++++++++++++++++++++++++++++++----------- |
| 1 file changed, 50 insertions(+), 17 deletions(-) |
| |
| --- a/net/vmw_vsock/vmci_transport.c |
| +++ b/net/vmw_vsock/vmci_transport.c |
| @@ -273,6 +273,31 @@ vmci_transport_send_control_pkt_bh(struc |
| } |
| |
| static int |
| +vmci_transport_alloc_send_control_pkt(struct sockaddr_vm *src, |
| + struct sockaddr_vm *dst, |
| + enum vmci_transport_packet_type type, |
| + u64 size, |
| + u64 mode, |
| + struct vmci_transport_waiting_info *wait, |
| + u16 proto, |
| + struct vmci_handle handle) |
| +{ |
| + struct vmci_transport_packet *pkt; |
| + int err; |
| + |
| + pkt = kmalloc(sizeof(*pkt), GFP_KERNEL); |
| + if (!pkt) |
| + return -ENOMEM; |
| + |
| + err = __vmci_transport_send_control_pkt(pkt, src, dst, type, size, |
| + mode, wait, proto, handle, |
| + true); |
| + kfree(pkt); |
| + |
| + return err; |
| +} |
| + |
| +static int |
| vmci_transport_send_control_pkt(struct sock *sk, |
| enum vmci_transport_packet_type type, |
| u64 size, |
| @@ -281,9 +306,7 @@ vmci_transport_send_control_pkt(struct s |
| u16 proto, |
| struct vmci_handle handle) |
| { |
| - struct vmci_transport_packet *pkt; |
| struct vsock_sock *vsk; |
| - int err; |
| |
| vsk = vsock_sk(sk); |
| |
| @@ -293,17 +316,10 @@ vmci_transport_send_control_pkt(struct s |
| 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, |
| - mode, wait, proto, handle, |
| - true); |
| - kfree(pkt); |
| - |
| - return err; |
| + 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, |
| @@ -321,12 +337,29 @@ static int vmci_transport_send_reset_bh( |
| 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, |
| - VMCI_TRANSPORT_PACKET_TYPE_RST, |
| - 0, 0, NULL, VSOCK_PROTO_INVALID, |
| - VMCI_INVALID_HANDLE); |
| + |
| + 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); |
| } |
| |
| static int vmci_transport_send_negotiate(struct sock *sk, size_t size) |