summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2015-02-24 22:01:33 +0800
committerMatt Johnston <matt@ucc.asn.au>2015-02-24 22:01:33 +0800
commit3b69efb18f84091de19a769f17d4ecbe6c44034d (patch)
treefc5e7858ce903ac99515b909c7d6c2c322c6a2ef
parent1908a6a766eeee58929c55c487aab0a59aa8090b (diff)
downloaddropbear-3b69efb18f84091de19a769f17d4ecbe6c44034d.tar.gz
Free memory before exiting. Based on patch from Thorsten Horstmann.
Client side is not complete.
-rw-r--r--common-session.c45
-rw-r--r--listener.c9
-rw-r--r--listener.h2
-rw-r--r--svr-chansession.c4
-rw-r--r--svr-session.c17
-rw-r--r--sysoptions.h3
6 files changed, 66 insertions, 14 deletions
diff --git a/common-session.c b/common-session.c
index d820d64..a225b21 100644
--- a/common-session.c
+++ b/common-session.c
@@ -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);
diff --git a/listener.c b/listener.c
index dd90c6b..a7f0730 100644
--- a/listener.c
+++ b/listener.c
@@ -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);
}
diff --git a/listener.h b/listener.h
index 317665f..b531ed6 100644
--- a/listener.h
+++ b/listener.h
@@ -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 */
diff --git a/svr-chansession.c b/svr-chansession.c
index 5bed8fc..5f9f56d 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -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");
}
+ */
}
diff --git a/svr-session.c b/svr-session.c
index 343cb30..2b8a956 100644
--- a/svr-session.c
+++ b/svr-session.c
@@ -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);
}
diff --git a/sysoptions.h b/sysoptions.h
index bec7246..03f4076 100644
--- a/sysoptions.h
+++ b/sysoptions.h
@@ -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"