fixed a use-after-free bug in dpd_timeout()
This commit is contained in:
@@ -2995,6 +2995,8 @@ terminate_connection(const char *nm)
|
|||||||
c->policy &= ~POLICY_UP;
|
c->policy &= ~POLICY_UP;
|
||||||
flush_pending_by_connection(c);
|
flush_pending_by_connection(c);
|
||||||
delete_states_by_connection(c, FALSE);
|
delete_states_by_connection(c, FALSE);
|
||||||
|
if (c->kind == CK_INSTANCE)
|
||||||
|
delete_connection(c, FALSE);
|
||||||
reset_cur_connection();
|
reset_cur_connection();
|
||||||
}
|
}
|
||||||
c = n;
|
c = n;
|
||||||
|
|||||||
+15
-4
@@ -5592,6 +5592,7 @@ dpd_timeout(struct state *st)
|
|||||||
struct state *newest_phase1_st;
|
struct state *newest_phase1_st;
|
||||||
struct connection *c = st->st_connection;
|
struct connection *c = st->st_connection;
|
||||||
int action = st->st_connection->dpd_action;
|
int action = st->st_connection->dpd_action;
|
||||||
|
char cname[BUF_LEN];
|
||||||
|
|
||||||
passert(action == DPD_ACTION_HOLD
|
passert(action == DPD_ACTION_HOLD
|
||||||
|| action == DPD_ACTION_CLEAR
|
|| action == DPD_ACTION_CLEAR
|
||||||
@@ -5622,20 +5623,30 @@ dpd_timeout(struct state *st)
|
|||||||
* leak traffic. Also, being in %trap means new packets will
|
* leak traffic. Also, being in %trap means new packets will
|
||||||
* force an initiation of the conn again.
|
* force an initiation of the conn again.
|
||||||
*/
|
*/
|
||||||
loglog(RC_LOG_SERIOUS, "DPD: Putting connection into %%trap");
|
loglog(RC_LOG_SERIOUS, "DPD: Putting connection \"%s\" into %%trap", c->name);
|
||||||
|
if (c->kind == CK_INSTANCE)
|
||||||
|
delete_connection(c, TRUE);
|
||||||
break;
|
break;
|
||||||
case DPD_ACTION_CLEAR:
|
case DPD_ACTION_CLEAR:
|
||||||
/* dpdaction=clear - Wipe the SA & eroute - everything */
|
/* dpdaction=clear - Wipe the SA & eroute - everything */
|
||||||
loglog(RC_LOG_SERIOUS, "DPD: Clearing connection");
|
loglog(RC_LOG_SERIOUS, "DPD: Clearing connection \"%s\"", c->name);
|
||||||
unroute_connection(c);
|
unroute_connection(c);
|
||||||
|
if (c->kind == CK_INSTANCE)
|
||||||
|
delete_connection(c, TRUE);
|
||||||
break;
|
break;
|
||||||
case DPD_ACTION_RESTART:
|
case DPD_ACTION_RESTART:
|
||||||
/* dpdaction=restart - Restart connection,
|
/* dpdaction=restart - Restart connection,
|
||||||
* except if roadwarrior connection
|
* except if roadwarrior connection
|
||||||
*/
|
*/
|
||||||
loglog(RC_LOG_SERIOUS, "DPD: Restarting connection");
|
loglog(RC_LOG_SERIOUS, "DPD: Restarting connection \"%s\"", c->name);
|
||||||
unroute_connection(c);
|
unroute_connection(c);
|
||||||
initiate_connection(c->name, NULL_FD);
|
|
||||||
|
/* caching the connection name before deletion */
|
||||||
|
strncpy(cname, c->name, BUF_LEN);
|
||||||
|
|
||||||
|
if (c->kind == CK_INSTANCE)
|
||||||
|
delete_connection(c, TRUE);
|
||||||
|
initiate_connection(cname, NULL_FD);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
loglog(RC_LOG_SERIOUS, "DPD: unknown action");
|
loglog(RC_LOG_SERIOUS, "DPD: unknown action");
|
||||||
|
|||||||
+3
-6
@@ -464,12 +464,7 @@ delete_states_by_connection(struct connection *c, bool relations)
|
|||||||
passert(sr->routing != RT_ROUTED_TUNNEL);
|
passert(sr->routing != RT_ROUTED_TUNNEL);
|
||||||
sr = sr->next;
|
sr = sr->next;
|
||||||
}
|
}
|
||||||
|
c->kind = ck;
|
||||||
if (ck == CK_INSTANCE)
|
|
||||||
{
|
|
||||||
c->kind = ck;
|
|
||||||
delete_connection(c, relations);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Walk through the state table, and delete each state whose phase 1 (IKE)
|
/* Walk through the state table, and delete each state whose phase 1 (IKE)
|
||||||
@@ -506,6 +501,8 @@ delete_states_by_peer(ip_address *peer)
|
|||||||
, peerstr
|
, peerstr
|
||||||
, c->name);
|
, c->name);
|
||||||
delete_states_by_connection(c, TRUE);
|
delete_states_by_connection(c, TRUE);
|
||||||
|
if (c->kind == CK_INSTANCE)
|
||||||
|
delete_connection(c, TRUE);
|
||||||
break; /* can only delete it once */
|
break; /* can only delete it once */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user