diff options
author | Andreas Schneider <asn@cryptomilk.org> | 2012-10-22 16:22:09 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2012-10-22 17:37:50 +0200 |
commit | 04f1d950b9dc903dc9ef9808240d22e08c369bd3 (patch) | |
tree | 896ff82dfd97e6172d37b35b215dc497b53c9c26 | |
parent | 191c0ae2bb9769db37042c95fdfc55cbe264fb99 (diff) | |
download | libssh-04f1d950b9dc903dc9ef9808240d22e08c369bd3.tar.gz libssh-04f1d950b9dc903dc9ef9808240d22e08c369bd3.tar.xz libssh-04f1d950b9dc903dc9ef9808240d22e08c369bd3.zip |
session: Fix a possible use after free in ssh_free().
We need to cleanup the channels first cause we call ssh_channel_close()
on the channels which still require a working socket and poll context.
Thanks to sh4rm4!
-rw-r--r-- | src/session.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/src/session.c b/src/session.c index 82788dc6..5d58fa59 100644 --- a/src/session.c +++ b/src/session.c @@ -164,10 +164,20 @@ void ssh_free(ssh_session session) { return; } - SAFE_FREE(session->serverbanner); - SAFE_FREE(session->clientbanner); - SAFE_FREE(session->bindaddr); - SAFE_FREE(session->banner); + /* delete all channels */ + while ((it=ssh_list_get_iterator(session->channels)) != NULL) { + ssh_channel_free(ssh_iterator_value(ssh_channel,it)); + ssh_list_remove(session->channels, it); + } + ssh_list_free(session->channels); + session->channels=NULL; + + ssh_socket_free(session->socket); + + if (session->default_poll_ctx) { + ssh_poll_ctx_free(session->default_poll_ctx); + } + #ifdef WITH_PCAP if(session->pcap_ctx){ ssh_pcap_context_free(session->pcap_ctx); @@ -183,17 +193,6 @@ void ssh_free(ssh_session session) { session->in_buffer=session->out_buffer=NULL; crypto_free(session->current_crypto); crypto_free(session->next_crypto); - ssh_socket_free(session->socket); - if(session->default_poll_ctx){ - ssh_poll_ctx_free(session->default_poll_ctx); - } - /* delete all channels */ - while ((it=ssh_list_get_iterator(session->channels)) != NULL) { - ssh_channel_free(ssh_iterator_value(ssh_channel,it)); - ssh_list_remove(session->channels, it); - } - ssh_list_free(session->channels); - session->channels=NULL; #ifndef _WIN32 agent_free(session->agent); #endif /* _WIN32 */ @@ -236,6 +235,11 @@ void ssh_free(ssh_session session) { ssh_list_free(session->identity); } + SAFE_FREE(session->serverbanner); + SAFE_FREE(session->clientbanner); + SAFE_FREE(session->bindaddr); + SAFE_FREE(session->banner); + /* options */ SAFE_FREE(session->username); SAFE_FREE(session->host); |