From 21ad460886af2902bf17e0e455dc54bcc2f8ebae Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 30 Jan 2020 16:37:58 -0500 Subject: [PATCH] fixes for 5.4 Signed-off-by: Sasha Levin --- ...k-remove-the-accept-port-restriction.patch | 168 ++++++++++++++++++ queue-5.4/series | 1 + 2 files changed, 169 insertions(+) create mode 100644 queue-5.4/hv_sock-remove-the-accept-port-restriction.patch diff --git a/queue-5.4/hv_sock-remove-the-accept-port-restriction.patch b/queue-5.4/hv_sock-remove-the-accept-port-restriction.patch new file mode 100644 index 00000000000..a27d09f17a9 --- /dev/null +++ b/queue-5.4/hv_sock-remove-the-accept-port-restriction.patch @@ -0,0 +1,168 @@ +From 1fc0e1d729a4c10257b61a4952dd91448062e83d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2020 03:08:18 +0000 +Subject: hv_sock: Remove the accept port restriction + +From: Sunil Muthuswamy + +[ Upstream commit c742c59e1fbd022b64d91aa9a0092b3a699d653c ] + +Currently, hv_sock restricts the port the guest socket can accept +connections on. hv_sock divides the socket port namespace into two parts +for server side (listening socket), 0-0x7FFFFFFF & 0x80000000-0xFFFFFFFF +(there are no restrictions on client port namespace). The first part +(0-0x7FFFFFFF) is reserved for sockets where connections can be accepted. +The second part (0x80000000-0xFFFFFFFF) is reserved for allocating ports +for the peer (host) socket, once a connection is accepted. +This reservation of the port namespace is specific to hv_sock and not +known by the generic vsock library (ex: af_vsock). This is problematic +because auto-binds/ephemeral ports are handled by the generic vsock +library and it has no knowledge of this port reservation and could +allocate a port that is not compatible with hv_sock (and legitimately so). +The issue hasn't surfaced so far because the auto-bind code of vsock +(__vsock_bind_stream) prior to the change 'VSOCK: bind to random port for +VMADDR_PORT_ANY' would start walking up from LAST_RESERVED_PORT (1023) and +start assigning ports. That will take a large number of iterations to hit +0x7FFFFFFF. But, after the above change to randomize port selection, the +issue has started coming up more frequently. +There has really been no good reason to have this port reservation logic +in hv_sock from the get go. Reserving a local port for peer ports is not +how things are handled generally. Peer ports should reflect the peer port. +This fixes the issue by lifting the port reservation, and also returns the +right peer port. Since the code converts the GUID to the peer port (by +using the first 4 bytes), there is a possibility of conflicts, but that +seems like a reasonable risk to take, given this is limited to vsock and +that only applies to all local sockets. + +Signed-off-by: Sunil Muthuswamy +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/vmw_vsock/hyperv_transport.c | 68 +++++--------------------------- + 1 file changed, 9 insertions(+), 59 deletions(-) + +diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c +index c443db7af8d4a..463cefc1e5ae2 100644 +--- a/net/vmw_vsock/hyperv_transport.c ++++ b/net/vmw_vsock/hyperv_transport.c +@@ -136,28 +136,15 @@ struct hvsock { + **************************************************************************** + * The only valid Service GUIDs, from the perspectives of both the host and * + * Linux VM, that can be connected by the other end, must conform to this * +- * format: -facb-11e6-bd58-64006a7986d3, and the "port" must be in * +- * this range [0, 0x7FFFFFFF]. * ++ * format: -facb-11e6-bd58-64006a7986d3. * + **************************************************************************** + * + * When we write apps on the host to connect(), the GUID ServiceID is used. + * When we write apps in Linux VM to connect(), we only need to specify the + * port and the driver will form the GUID and use that to request the host. + * +- * From the perspective of Linux VM: +- * 1. the local ephemeral port (i.e. the local auto-bound port when we call +- * connect() without explicit bind()) is generated by __vsock_bind_stream(), +- * and the range is [1024, 0xFFFFFFFF). +- * 2. the remote ephemeral port (i.e. the auto-generated remote port for +- * a connect request initiated by the host's connect()) is generated by +- * hvs_remote_addr_init() and the range is [0x80000000, 0xFFFFFFFF). + */ + +-#define MAX_LISTEN_PORT ((u32)0x7FFFFFFF) +-#define MAX_VM_LISTEN_PORT MAX_LISTEN_PORT +-#define MAX_HOST_LISTEN_PORT MAX_LISTEN_PORT +-#define MIN_HOST_EPHEMERAL_PORT (MAX_HOST_LISTEN_PORT + 1) +- + /* 00000000-facb-11e6-bd58-64006a7986d3 */ + static const guid_t srv_id_template = + GUID_INIT(0x00000000, 0xfacb, 0x11e6, 0xbd, 0x58, +@@ -180,33 +167,6 @@ static void hvs_addr_init(struct sockaddr_vm *addr, const guid_t *svr_id) + vsock_addr_init(addr, VMADDR_CID_ANY, port); + } + +-static void hvs_remote_addr_init(struct sockaddr_vm *remote, +- struct sockaddr_vm *local) +-{ +- static u32 host_ephemeral_port = MIN_HOST_EPHEMERAL_PORT; +- struct sock *sk; +- +- vsock_addr_init(remote, VMADDR_CID_ANY, VMADDR_PORT_ANY); +- +- while (1) { +- /* Wrap around ? */ +- if (host_ephemeral_port < MIN_HOST_EPHEMERAL_PORT || +- host_ephemeral_port == VMADDR_PORT_ANY) +- host_ephemeral_port = MIN_HOST_EPHEMERAL_PORT; +- +- remote->svm_port = host_ephemeral_port++; +- +- sk = vsock_find_connected_socket(remote, local); +- if (!sk) { +- /* Found an available ephemeral port */ +- return; +- } +- +- /* Release refcnt got in vsock_find_connected_socket */ +- sock_put(sk); +- } +-} +- + static void hvs_set_channel_pending_send_size(struct vmbus_channel *chan) + { + set_channel_pending_send_size(chan, +@@ -336,12 +296,7 @@ static void hvs_open_connection(struct vmbus_channel *chan) + if_type = &chan->offermsg.offer.if_type; + if_instance = &chan->offermsg.offer.if_instance; + conn_from_host = chan->offermsg.offer.u.pipe.user_def[0]; +- +- /* The host or the VM should only listen on a port in +- * [0, MAX_LISTEN_PORT] +- */ +- if (!is_valid_srv_id(if_type) || +- get_port_by_srv_id(if_type) > MAX_LISTEN_PORT) ++ if (!is_valid_srv_id(if_type)) + return; + + hvs_addr_init(&addr, conn_from_host ? if_type : if_instance); +@@ -365,6 +320,13 @@ static void hvs_open_connection(struct vmbus_channel *chan) + + new->sk_state = TCP_SYN_SENT; + vnew = vsock_sk(new); ++ ++ hvs_addr_init(&vnew->local_addr, if_type); ++ ++ /* Remote peer is always the host */ ++ vsock_addr_init(&vnew->remote_addr, ++ VMADDR_CID_HOST, VMADDR_PORT_ANY); ++ vnew->remote_addr.svm_port = get_port_by_srv_id(if_instance); + hvs_new = vnew->trans; + hvs_new->chan = chan; + } else { +@@ -429,8 +391,6 @@ static void hvs_open_connection(struct vmbus_channel *chan) + sk->sk_ack_backlog++; + + hvs_addr_init(&vnew->local_addr, if_type); +- hvs_remote_addr_init(&vnew->remote_addr, &vnew->local_addr); +- + hvs_new->vm_srv_id = *if_type; + hvs_new->host_srv_id = *if_instance; + +@@ -753,16 +713,6 @@ static bool hvs_stream_is_active(struct vsock_sock *vsk) + + static bool hvs_stream_allow(u32 cid, u32 port) + { +- /* The host's port range [MIN_HOST_EPHEMERAL_PORT, 0xFFFFFFFF) is +- * reserved as ephemeral ports, which are used as the host's ports +- * when the host initiates connections. +- * +- * Perform this check in the guest so an immediate error is produced +- * instead of a timeout. +- */ +- if (port > MAX_HOST_LISTEN_PORT) +- return false; +- + if (cid == VMADDR_CID_HOST) + return true; + +-- +2.20.1 + diff --git a/queue-5.4/series b/queue-5.4/series index c6af33c6b08..de6f5886abd 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -108,3 +108,4 @@ crypto-pcrypt-fix-user-after-free-on-module-unload.patch kvm-arm64-write-arch.mdcr_el2-changes-since-last-vcpu_load-on-vhe.patch revert-um-enable-config_constructors.patch power-supply-ingenic-battery-don-t-change-scale-if-there-s-only-one.patch +hv_sock-remove-the-accept-port-restriction.patch -- 2.47.3