diff options
| author | Jorgen Hansen <jhansen@vmware.com> | 2018-12-18 03:34:06 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2018-12-18 14:53:42 -0500 |
| commit | a915b982d8f5e4295f64b8dd37ce753874867e88 (patch) | |
| tree | 0c16321ceef6295f5b8e7215860679388e879a7b /net | |
| parent | fde9cd69a59f7ee405c87fff84bc08fa2a550e47 (diff) | |
VSOCK: Send reset control packet when socket is partially bound
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>
Diffstat (limited to 'net')
| -rw-r--r-- | net/vmw_vsock/vmci_transport.c | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index cb332adb84cd..c361ce782412 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c | |||
| @@ -264,6 +264,31 @@ vmci_transport_send_control_pkt_bh(struct sockaddr_vm *src, | |||
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | static int | 266 | static int |
| 267 | vmci_transport_alloc_send_control_pkt(struct sockaddr_vm *src, | ||
| 268 | struct sockaddr_vm *dst, | ||
| 269 | enum vmci_transport_packet_type type, | ||
| 270 | u64 size, | ||
| 271 | u64 mode, | ||
| 272 | struct vmci_transport_waiting_info *wait, | ||
| 273 | u16 proto, | ||
| 274 | struct vmci_handle handle) | ||
| 275 | { | ||
| 276 | struct vmci_transport_packet *pkt; | ||
| 277 | int err; | ||
| 278 | |||
| 279 | pkt = kmalloc(sizeof(*pkt), GFP_KERNEL); | ||
| 280 | if (!pkt) | ||
| 281 | return -ENOMEM; | ||
| 282 | |||
| 283 | err = __vmci_transport_send_control_pkt(pkt, src, dst, type, size, | ||
| 284 | mode, wait, proto, handle, | ||
| 285 | true); | ||
| 286 | kfree(pkt); | ||
| 287 | |||
| 288 | return err; | ||
| 289 | } | ||
| 290 | |||
| 291 | static int | ||
| 267 | vmci_transport_send_control_pkt(struct sock *sk, | 292 | vmci_transport_send_control_pkt(struct sock *sk, |
| 268 | enum vmci_transport_packet_type type, | 293 | enum vmci_transport_packet_type type, |
| 269 | u64 size, | 294 | u64 size, |
| @@ -272,9 +297,7 @@ vmci_transport_send_control_pkt(struct sock *sk, | |||
| 272 | u16 proto, | 297 | u16 proto, |
| 273 | struct vmci_handle handle) | 298 | struct vmci_handle handle) |
| 274 | { | 299 | { |
| 275 | struct vmci_transport_packet *pkt; | ||
| 276 | struct vsock_sock *vsk; | 300 | struct vsock_sock *vsk; |
| 277 | int err; | ||
| 278 | 301 | ||
| 279 | vsk = vsock_sk(sk); | 302 | vsk = vsock_sk(sk); |
| 280 | 303 | ||
| @@ -284,17 +307,10 @@ vmci_transport_send_control_pkt(struct sock *sk, | |||
| 284 | if (!vsock_addr_bound(&vsk->remote_addr)) | 307 | if (!vsock_addr_bound(&vsk->remote_addr)) |
| 285 | return -EINVAL; | 308 | return -EINVAL; |
| 286 | 309 | ||
| 287 | pkt = kmalloc(sizeof(*pkt), GFP_KERNEL); | 310 | return vmci_transport_alloc_send_control_pkt(&vsk->local_addr, |
| 288 | if (!pkt) | 311 | &vsk->remote_addr, |
| 289 | return -ENOMEM; | 312 | type, size, mode, |
| 290 | 313 | wait, proto, handle); | |
| 291 | err = __vmci_transport_send_control_pkt(pkt, &vsk->local_addr, | ||
| 292 | &vsk->remote_addr, type, size, | ||
| 293 | mode, wait, proto, handle, | ||
| 294 | true); | ||
| 295 | kfree(pkt); | ||
| 296 | |||
| 297 | return err; | ||
| 298 | } | 314 | } |
| 299 | 315 | ||
| 300 | static int vmci_transport_send_reset_bh(struct sockaddr_vm *dst, | 316 | static int vmci_transport_send_reset_bh(struct sockaddr_vm *dst, |
| @@ -312,12 +328,29 @@ static int vmci_transport_send_reset_bh(struct sockaddr_vm *dst, | |||
| 312 | static int vmci_transport_send_reset(struct sock *sk, | 328 | static int vmci_transport_send_reset(struct sock *sk, |
| 313 | struct vmci_transport_packet *pkt) | 329 | struct vmci_transport_packet *pkt) |
| 314 | { | 330 | { |
| 331 | struct sockaddr_vm *dst_ptr; | ||
| 332 | struct sockaddr_vm dst; | ||
| 333 | struct vsock_sock *vsk; | ||
| 334 | |||
| 315 | if (pkt->type == VMCI_TRANSPORT_PACKET_TYPE_RST) | 335 | if (pkt->type == VMCI_TRANSPORT_PACKET_TYPE_RST) |
| 316 | return 0; | 336 | return 0; |
| 317 | return vmci_transport_send_control_pkt(sk, | 337 | |
| 318 | VMCI_TRANSPORT_PACKET_TYPE_RST, | 338 | vsk = vsock_sk(sk); |
| 319 | 0, 0, NULL, VSOCK_PROTO_INVALID, | 339 | |
| 320 | VMCI_INVALID_HANDLE); | 340 | if (!vsock_addr_bound(&vsk->local_addr)) |
| 341 | return -EINVAL; | ||
| 342 | |||
| 343 | if (vsock_addr_bound(&vsk->remote_addr)) { | ||
| 344 | dst_ptr = &vsk->remote_addr; | ||
| 345 | } else { | ||
| 346 | vsock_addr_init(&dst, pkt->dg.src.context, | ||
| 347 | pkt->src_port); | ||
| 348 | dst_ptr = &dst; | ||
| 349 | } | ||
| 350 | return vmci_transport_alloc_send_control_pkt(&vsk->local_addr, dst_ptr, | ||
| 351 | VMCI_TRANSPORT_PACKET_TYPE_RST, | ||
| 352 | 0, 0, NULL, VSOCK_PROTO_INVALID, | ||
| 353 | VMCI_INVALID_HANDLE); | ||
| 321 | } | 354 | } |
| 322 | 355 | ||
| 323 | static int vmci_transport_send_negotiate(struct sock *sk, size_t size) | 356 | static int vmci_transport_send_negotiate(struct sock *sk, size_t size) |
