From a48e7f8b473f2d97e0eb5b6a1011507888c5e837 Mon Sep 17 00:00:00 2001 From: Norbert Federa Date: Thu, 20 Feb 2020 17:26:27 +0100 Subject: [PATCH] core: fix endless loops waiting for activation There are two loops polling the transport pdu receiver in non-blocking mode when waiting for reaching CONNECTION_STATE_ACTIVE rdp state. In case of an invalid pdu size in the tpkt header this leaded to an endless loop, utilizing 100% of a cpu core. Added a sleep and limited the max loop time to the tcp ack timout value. --- libfreerdp/core/activation.c | 15 +++++++++++---- libfreerdp/core/connection.c | 13 +++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/libfreerdp/core/activation.c b/libfreerdp/core/activation.c index 98381e2..51d95da 100644 --- a/libfreerdp/core/activation.c +++ b/libfreerdp/core/activation.c @@ -24,6 +24,8 @@ #include "activation.h" #include "display.h" +#define TAG FREERDP_TAG("core.activation") + /* static const char* const CTRLACTION_STRINGS[] = { @@ -255,6 +257,7 @@ BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp) BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s) { UINT16 lengthSourceDescriptor; + UINT32 timeout; if (rdp->state == CONNECTION_STATE_ACTIVE) rdp->deactivation_reactivation = TRUE; @@ -288,18 +291,22 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s) rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE); - while (rdp->state != CONNECTION_STATE_ACTIVE) + for (timeout = 0; timeout < rdp->settings->TcpAckTimeout; timeout += 100) { if (rdp_check_fds(rdp) < 0) return FALSE; if (freerdp_shall_disconnect(rdp->instance)) - break; + return TRUE; - SwitchToThread(); + if (rdp->state == CONNECTION_STATE_ACTIVE) + return TRUE; + + Sleep(100); } - return TRUE; + WLog_ERR(TAG, "Timeout waiting for activation"); + return FALSE; } BOOL rdp_send_deactivate_all(rdpRdp* rdp) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 3643d0f..817fbba 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -233,6 +233,7 @@ BOOL rdp_client_connect(rdpRdp* rdp) /* make sure SSL is initialize for earlier enough for crypto, by taking advantage of winpr SSL * FIPS flag for openssl initialization */ DWORD flags = WINPR_SSL_INIT_DEFAULT; + UINT32 timeout; if (!rdp_client_reset_codecs(rdp->context)) return FALSE; @@ -361,18 +362,22 @@ BOOL rdp_client_connect(rdpRdp* rdp) return FALSE; } - while (rdp->state != CONNECTION_STATE_ACTIVE) + for (timeout = 0; timeout < settings->TcpAckTimeout; timeout += 100) { if (rdp_check_fds(rdp) < 0) { freerdp_set_last_error_if_not(rdp->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED); - return FALSE; } - SwitchToThread(); + + if (rdp->state == CONNECTION_STATE_ACTIVE) + return TRUE; + + Sleep(100); } - return TRUE; + WLog_ERR(TAG, "Timeout waiting for activation"); + return FALSE; } BOOL rdp_client_disconnect(rdpRdp* rdp) -- 2.7.4