1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-12-02 01:17:52 +03:00

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!
This commit is contained in:
Andreas Schneider
2012-10-22 16:32:08 +02:00
parent f2e498c7db
commit 166ccef8dc

View File

@@ -166,37 +166,51 @@ void ssh_free(ssh_session session) {
if (session == NULL) { if (session == NULL) {
return; return;
} }
enter_function();
SAFE_FREE(session->serverbanner); /*
SAFE_FREE(session->clientbanner); * Delete all channels
SAFE_FREE(session->banner); *
#ifdef WITH_PCAP * This needs the first thing we clean up cause if there is still an open
if(session->pcap_ctx){ * channel we call ssh_channel_close() first. So we need a working socket
ssh_pcap_context_free(session->pcap_ctx); * and poll context for it.
session->pcap_ctx=NULL; */
} for (it = ssh_list_get_iterator(session->channels);
#endif it != NULL;
ssh_buffer_free(session->in_buffer); it = ssh_list_get_iterator(session->channels)) {
ssh_buffer_free(session->out_buffer); ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
if(session->in_hashbuf != NULL) ssh_list_remove(session->channels, it);
ssh_buffer_free(session->in_hashbuf);
if(session->out_hashbuf != NULL)
ssh_buffer_free(session->out_hashbuf);
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_do_free(ssh_iterator_value(ssh_channel,it));
ssh_list_remove(session->channels, it);
} }
ssh_list_free(session->channels); ssh_list_free(session->channels);
session->channels=NULL; session->channels = NULL;
#ifdef WITH_PCAP
if (session->pcap_ctx) {
ssh_pcap_context_free(session->pcap_ctx);
session->pcap_ctx = NULL;
}
#endif
ssh_socket_free(session->socket);
session->socket = NULL;
if (session->default_poll_ctx) {
ssh_poll_ctx_free(session->default_poll_ctx);
}
ssh_buffer_free(session->in_buffer);
ssh_buffer_free(session->out_buffer);
session->in_buffer = session->out_buffer = NULL;
if (session->in_hashbuf != NULL) {
ssh_buffer_free(session->in_hashbuf);
}
if (session->out_hashbuf != NULL) {
ssh_buffer_free(session->out_hashbuf);
}
crypto_free(session->current_crypto);
crypto_free(session->next_crypto);
#ifndef _WIN32 #ifndef _WIN32
agent_free(session->agent); agent_free(session->agent);
#endif /* _WIN32 */ #endif /* _WIN32 */
@@ -204,30 +218,37 @@ void ssh_free(ssh_session session) {
ssh_key_free(session->srv.dsa_key); ssh_key_free(session->srv.dsa_key);
ssh_key_free(session->srv.rsa_key); ssh_key_free(session->srv.rsa_key);
if(session->ssh_message_list){ if (session->ssh_message_list) {
ssh_message msg; ssh_message msg;
while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
!= NULL){ for (msg = ssh_list_pop_head(ssh_message, session->ssh_message_list);
ssh_message_free(msg); msg != NULL;
} msg = ssh_list_pop_head(ssh_message, session->ssh_message_list)) {
ssh_list_free(session->ssh_message_list); ssh_message_free(msg);
}
ssh_list_free(session->ssh_message_list);
} }
if (session->packet_callbacks) if (session->packet_callbacks) {
ssh_list_free(session->packet_callbacks); ssh_list_free(session->packet_callbacks);
}
/* options */ /* options */
if (session->opts.identity) { if (session->opts.identity) {
char *id; char *id;
for (id = ssh_list_pop_head(char *, session->opts.identity); for (id = ssh_list_pop_head(char *, session->opts.identity);
id != NULL; id != NULL;
id = ssh_list_pop_head(char *, session->opts.identity)) { id = ssh_list_pop_head(char *, session->opts.identity)) {
SAFE_FREE(id); SAFE_FREE(id);
} }
ssh_list_free(session->opts.identity); ssh_list_free(session->opts.identity);
} }
SAFE_FREE(session->serverbanner);
SAFE_FREE(session->clientbanner);
SAFE_FREE(session->banner);
SAFE_FREE(session->opts.bindaddr); SAFE_FREE(session->opts.bindaddr);
SAFE_FREE(session->opts.username); SAFE_FREE(session->opts.username);
SAFE_FREE(session->opts.host); SAFE_FREE(session->opts.host);