From: Sasha Levin Date: Thu, 30 Jan 2020 21:37:58 +0000 (-0500) Subject: fixes for 4.14 X-Git-Tag: v5.5.1~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8a936b45454276275273c1a103293816105c0dbd;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 4.14 Signed-off-by: Sasha Levin --- diff --git a/queue-4.14/hv_sock-remove-the-accept-port-restriction.patch b/queue-4.14/hv_sock-remove-the-accept-port-restriction.patch new file mode 100644 index 00000000000..00064c7ceb7 --- /dev/null +++ b/queue-4.14/hv_sock-remove-the-accept-port-restriction.patch @@ -0,0 +1,168 @@ +From ce137a90f152310d37d032e54c0bce36ab96e9d4 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 6614512f81800..736b76ec8cf01 100644 +--- a/net/vmw_vsock/hyperv_transport.c ++++ b/net/vmw_vsock/hyperv_transport.c +@@ -144,28 +144,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 uuid_le srv_id_template = + UUID_LE(0x00000000, 0xfacb, 0x11e6, 0xbd, 0x58, +@@ -188,33 +175,6 @@ static void hvs_addr_init(struct sockaddr_vm *addr, const uuid_le *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, +@@ -342,12 +302,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); +@@ -372,6 +327,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 { +@@ -411,8 +373,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; + +@@ -717,16 +677,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-4.14/series b/queue-4.14/series index 7d5942c53e7..19af0bf7505 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -30,3 +30,4 @@ usb-storage-disable-uas-on-jmicron-sata-enclosure.patch net_sched-ematch-reject-invalid-tcf_em_simple.patch rsi-fix-use-after-free-on-probe-errors.patch crypto-af_alg-use-bh_lock_sock-in-sk_destruct.patch +hv_sock-remove-the-accept-port-restriction.patch