From 2cd233cd0c70ffa7ac4ca7ef2db400f920f2a468 Mon Sep 17 00:00:00 2001 From: Alex Leitner Date: Sat, 9 Mar 2024 01:17:17 +0000 Subject: [PATCH] GUACAMOLE-1732: Prevent deadlock and enhance cleanup in RDP client. --- src/protocols/rdp/client.c | 10 +++++++++- src/protocols/rdp/rdp.c | 12 ++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index e98a0f3a54..9090aee078 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -35,6 +35,7 @@ #include "common-ssh/user.h" #endif +#include #include #include #include @@ -241,6 +242,14 @@ int guac_rdp_client_free_handler(guac_client* client) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + /* + * Signals any threads that are blocked awaiting user input for authentication + * (e.g., username or password) to terminate their wait. By broadcasting a + * condition signal, the authentication process is interrupted, allowing for + * premature termination and cleanup during client disconnection. + */ + guac_argv_stop(); + /* Wait for client thread */ pthread_join(rdp_client->client_thread, NULL); @@ -306,4 +315,3 @@ int guac_rdp_client_free_handler(guac_client* client) { return 0; } - diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 1a16780b5f..2c00cf6c5c 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -525,12 +525,24 @@ static int guac_rdp_handle_connection(guac_client* client) { /* Set default pointer */ guac_common_cursor_set_pointer(rdp_client->display->cursor); + /* + * Downgrade the lock to allow for concurrent read access + * Access to read locks need to be made available for other processes to use + * while we await credentials from the user. + */ + pthread_rwlock_unlock(&(rdp_client->lock)); + pthread_rwlock_rdlock(&(rdp_client->lock)); + /* Connect to RDP server */ if (!freerdp_connect(rdp_inst)) { guac_rdp_client_abort(client, rdp_inst); goto fail; } + /* Upgrade to write lock again for further exclusive operations */ + pthread_rwlock_unlock(&(rdp_client->lock)); + pthread_rwlock_wrlock(&(rdp_client->lock)); + /* Connection complete */ rdp_client->rdp_inst = rdp_inst;