diff -u pioneers-0.9.55/debian/changelog pioneers-0.9.55/debian/changelog --- pioneers-0.9.55/debian/changelog +++ pioneers-0.9.55/debian/changelog @@ -1,3 +1,15 @@ +pioneers (0.9.55-1ubuntu0.1) dapper-security; urgency=low + + * SECURITY UPDATE: Denial of service by triggering delete operation on + server while Session is in use. (LP: #163056) + * common/network.[ch], common/state.c: Check that the session is unused + before freeing it. Patches from upstream, applied inline. + * References + CVE-2007-5933 + CVE-2007-6010 + + -- William Grant Wed, 28 Nov 2007 21:33:20 +1100 + pioneers (0.9.55-1) unstable; urgency=high * Upstream CVS snapshot release. (Closes: #351034) only in patch2: unchanged: --- pioneers-0.9.55.orig/common/network.h +++ pioneers-0.9.55/common/network.h @@ -97,7 +97,11 @@ */ gint net_accept(gint accept_fd, gchar ** error_message); -void net_close(Session * ses); +/** Close a session + * @param ses The session to close + * @return TRUE if the session can be removed + */ +gboolean net_close(Session * ses); void net_close_when_flushed(Session * ses); void net_wait_for_close(Session * ses); void net_printf(Session * ses, const gchar * fmt, ...); only in patch2: unchanged: --- pioneers-0.9.55.orig/common/state.c +++ pioneers-0.9.55/common/state.c @@ -66,29 +66,33 @@ static void route_event(StateMachine * sm, gint event) { - StateFunc curr_state; + StateFunc curr_state = NULL; gpointer user_data; if (sm->is_dead) return; - curr_state = sm_current(sm); + if (sm->stack_ptr >= 0) + curr_state = sm_current(sm); + user_data = sm->user_data; if (user_data == NULL) user_data = sm; switch (event) { case SM_ENTER: - curr_state(user_data, event); + if (curr_state) + curr_state(user_data, event); break; case SM_INIT: - curr_state(user_data, event); + if (curr_state) + curr_state(user_data, event); if (!sm->is_dead && sm->global !=NULL) sm->global (user_data, event); break; case SM_RECV: sm_cancel_prefix(sm); - if (curr_state(user_data, event)) + if (curr_state && curr_state(user_data, event)) break; sm_cancel_prefix(sm); if (!sm->is_dead @@ -102,7 +106,8 @@ case SM_NET_CLOSE: net_free(&(sm->ses)); default: - curr_state(user_data, event); + if (curr_state) + curr_state(user_data, event); if (!sm->is_dead && sm->global !=NULL) sm->global (user_data, event); break; @@ -672,6 +677,7 @@ { if (sm->ses != NULL) { net_free(&(sm->ses)); + g_return_if_fail(sm->ses == NULL); } if (sm->use_count > 0) sm->is_dead = TRUE; only in patch2: unchanged: --- pioneers-0.9.55.orig/common/network.c +++ pioneers-0.9.55/common/network.c @@ -130,7 +130,7 @@ ses->notify_func(event, ses->user_data, line); } -void net_close(Session * ses) +gboolean net_close(Session * ses) { if (ses->fd >= 0) { listen_read(ses, FALSE); @@ -146,6 +146,7 @@ g_free(data); } } + return !ses->entered; } void net_close_when_flushed(Session * ses) @@ -154,8 +155,8 @@ if (ses->write_queue != NULL) return; - net_close(ses); - notify(ses, NET_CLOSE, NULL); + if (net_close(ses)) + notify(ses, NET_CLOSE, NULL); } void net_wait_for_close(Session * ses) @@ -165,8 +166,8 @@ static void close_and_callback(Session * ses) { - net_close(ses); - notify(ses, NET_CLOSE, NULL); + if (net_close(ses)) + notify(ses, NET_CLOSE, NULL); } static void write_ready(Session * ses) @@ -378,6 +379,9 @@ ses->read_len = 0; ses->entered = FALSE; + if (ses->fd < 0) { + close_and_callback(ses); + } } Session *net_new(NetNotifyFunc notify_func, void *user_data) @@ -551,7 +555,10 @@ /* Free and NULL-ity the session *ses */ void net_free(Session ** ses) { - net_close(*ses); + /* If the sessions is still in use, do not free it */ + if (!net_close(*ses)) { + return; + } if ((*ses)->host != NULL) g_free((*ses)->host);