aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Schneider <asn@cryptomilk.org>2012-10-22 16:22:09 +0200
committerAndreas Schneider <asn@cryptomilk.org>2012-10-22 17:37:50 +0200
commit04f1d950b9dc903dc9ef9808240d22e08c369bd3 (patch)
tree896ff82dfd97e6172d37b35b215dc497b53c9c26
parent191c0ae2bb9769db37042c95fdfc55cbe264fb99 (diff)
downloadlibssh-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.c34
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);