Free memory before exiting. Based on patch from Thorsten Horstmann.

Client side is not complete.
This commit is contained in:
Matt Johnston 2015-02-24 22:01:33 +08:00
parent 4b1f5ec7c2
commit 21bed0d21a
6 changed files with 67 additions and 15 deletions

View File

@ -240,6 +240,15 @@ void session_loop(void(*loophandler)()) {
/* Not reached */
}
static void cleanup_buf(buffer **buf) {
if (!*buf) {
return;
}
buf_burn(*buf);
buf_free(*buf);
*buf = NULL;
}
/* clean up a session on exit */
void session_cleanup() {
@ -256,19 +265,31 @@ void session_cleanup() {
}
chancleanup();
/* Cleaning up keys must happen after other cleanup
functions which might queue packets */
if (ses.session_id) {
buf_burn(ses.session_id);
buf_free(ses.session_id);
ses.session_id = NULL;
}
if (ses.hash) {
buf_burn(ses.hash);
buf_free(ses.hash);
ses.hash = NULL;
/* Most dropbear functions are unsafe to run after this point */
#ifdef DROPBEAR_CLEANUP
/* listeners call cleanup functions, this should occur before
other session state is freed. */
remove_all_listeners();
while (!isempty(&ses.writequeue)) {
buf_free(dequeue(&ses.writequeue));
}
m_free(ses.remoteident);
m_free(ses.authstate.pw_dir);
m_free(ses.authstate.pw_name);
m_free(ses.authstate.pw_shell);
m_free(ses.authstate.pw_passwd);
m_free(ses.authstate.username);
#endif
cleanup_buf(&ses.session_id);
cleanup_buf(&ses.hash);
cleanup_buf(&ses.payload);
cleanup_buf(&ses.readbuf);
cleanup_buf(&ses.writepayload);
m_burn(ses.keys, sizeof(struct key_context));
m_free(ses.keys);

View File

@ -161,5 +161,14 @@ void remove_listener(struct Listener* listener) {
}
ses.listeners[listener->index] = NULL;
m_free(listener);
}
void remove_all_listeners(void) {
unsigned int i;
for (i = 0; i < ses.listensize; i++) {
if (ses.listeners[i]) {
remove_listener(ses.listeners[i]);
}
}
m_free(ses.listeners);
}

View File

@ -60,4 +60,6 @@ struct Listener * get_listener(int type, void* typedata,
void remove_listener(struct Listener* listener);
void remove_all_listeners(void);
#endif /* DROPBEAR_LISTENER_H */

View File

@ -787,9 +787,11 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
TRACE(("back to normal sigchld"))
/* Revert to normal sigchld handling */
/*
if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
dropbear_exit("signal() error");
}
*/
/* redirect stdin/stdout/stderr */
close(chansess->master);
@ -1005,9 +1007,11 @@ void svr_chansessinitialise() {
sa_chld.sa_handler = sesssigchild_handler;
sa_chld.sa_flags = SA_NOCLDSTOP;
sigemptyset(&sa_chld.sa_mask);
/*
if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) {
dropbear_exit("signal() error");
}
*/
}

View File

@ -78,10 +78,13 @@ static const struct ChanType *svr_chantypes[] = {
};
static void
svr_session_cleanup(void)
{
svr_session_cleanup(void) {
/* free potential public key options */
svr_pubkey_options_cleanup();
m_free(svr_ses.addrstring);
m_free(svr_ses.childpids);
m_free(svr_ses.remotehost);
}
static void
@ -150,6 +153,7 @@ void svr_session(int sock, int childpipe) {
void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
char fmtbuf[300];
int i;
if (!sessinitdone) {
/* before session init */
@ -183,6 +187,15 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
session_cleanup();
}
if (svr_opts.hostkey) {
sign_key_free(svr_opts.hostkey);
svr_opts.hostkey = NULL;
}
for (i = 0; i < DROPBEAR_MAX_PORTS; i++) {
m_free(svr_opts.addresses[i]);
m_free(svr_opts.ports[i]);
}
exit(exitcode);
}

View File

@ -256,6 +256,9 @@
#define DROPBEAR_LISTEN_BACKLOG MAX_CHANNELS
#endif
/* free memory before exiting */
#define DROPBEAR_CLEANUP
/* Use this string since some implementations might special-case it */
#define DROPBEAR_KEEPALIVE_STRING "keepalive@openssh.com"