GUACAMOLE-384: fixing segfault during ssh disconnect 118/head
authorsanhex <sanhex@gmail.com>
Wed, 18 Oct 2017 19:08:32 +0000 (12:08 -0700)
committersanhex <sanhex@gmail.com>
Mon, 30 Oct 2017 01:11:15 +0000 (18:11 -0700)
commitd33bd8deff9c7964a3a9c997c5c882d09dfed87b
tree0959a9db6432aec6a9218a462408d82f41f3c710
parent3c7a09f52bb576e5dab720b571e580b7e0acec43
GUACAMOLE-384: fixing segfault during ssh disconnect

Root Cause:
See the core dump and Valgrind report posted on Jira. guacd was reading a ssh terminal which had been freed. When a ssh connection is terminated, guac_ssh_client_free_handler() will be called from guacd_exec_proc() -> guac_client_free() with pointer client->free_handler. In guac_ssh_client_free_handler(), when ssh_client->term is freed, ssh_client->client_thread may still be using the ssh_client->term. It causes the crash reported in this bug.

The stack trace exposing the problem can be found by running guacd under Valgrind with a ssh test script. The test script repeats doing ssh login and logout for 5000 times.

Solution:
In guac_ssh_client_free_handler(), before calling guac_terminal_free(ssh_client->term), close the stdin pipe of the terminal to stop reading the pipe with guac_terminal_read_stdin() in ssh_input_thread(). So that ssh_input_thread() can be terminated in this case. Call pthread_join() to wait for ssh_client_thread() terminating before freeing the terminal.

Add a new function guac_terminal_stop() to close the pipe and set the fds to invalid (-1). Call it in guac_ssh_client_free_handler() and guac_terminal_free().

Checking the client running state in ssh_input_thread() and ssh_client_thread() to make sure they can be terminated when the client is stopped in guacd_exec_proc() by another thread.

Test:
- Confirmed ssh connection works normally.
- Observed the child process of guacd exits when ssh connection is terminated.
- Reran the ssh test script. Observed no crash.
src/protocols/ssh/client.c
src/protocols/ssh/ssh.c
src/terminal/terminal.c
src/terminal/terminal/terminal.h