connectd: don't keep around more than one old connection.

This was fixed in 1c495ca5a8 ("connectd:
fix accidental handling of old reconnections.") and then reverted by
the rework in "connectd: avoid use-after-free upon multiple
reconnections by a peer".

The latter made the race much less likely, since we cleaned up the
reconnecting struct once the connection was hung up by the remote
node, but it's still theoretically possible.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2022-06-19 16:01:42 +09:30
parent afbddcf7f3
commit fd90e5746b
3 changed files with 18 additions and 5 deletions

View file

@ -239,7 +239,8 @@ static struct io_plan *retry_peer_connected(struct io_conn *conn,
/*~ Usually the pattern is to return this directly. */
return peer_connected(conn, pr->daemon, &pr->id, &pr->addr,
pr->remote_addr,
&pr->cs, take(pr->their_features), pr->incoming);
&pr->cs, take(pr->their_features), pr->incoming,
true);
}
/*~ If we already know about this peer, we tell lightningd and it disconnects
@ -334,7 +335,8 @@ struct io_plan *peer_connected(struct io_conn *conn,
const struct wireaddr *remote_addr,
struct crypto_state *cs,
const u8 *their_features TAKES,
bool incoming)
bool incoming,
bool retrying)
{
u8 *msg;
struct peer *peer;
@ -344,9 +346,18 @@ struct io_plan *peer_connected(struct io_conn *conn,
bool option_gossip_queries;
peer = peer_htable_get(&daemon->peers, id);
if (peer)
if (peer) {
/* If we were already retrying, we only get one chance: there
* can be multiple reconnections, and we must not keep around
* stale ones */
if (retrying) {
if (taken(their_features))
tal_free(their_features);
return io_close(conn);
}
return peer_reconnected(conn, daemon, id, addr, remote_addr, cs,
their_features, incoming);
}
/* We promised we'd take it by marking it TAKEN above; prepare to free it. */
if (taken(their_features))

View file

@ -212,7 +212,8 @@ struct io_plan *peer_connected(struct io_conn *conn,
const struct wireaddr *remote_addr,
struct crypto_state *cs,
const u8 *their_features TAKES,
bool incoming);
bool incoming,
bool retrying);
/* Called when peer->peer_conn is finally freed */
void peer_conn_closed(struct peer *peer);

View file

@ -137,7 +137,8 @@ static struct io_plan *peer_init_received(struct io_conn *conn,
remote_addr,
&peer->cs,
take(features),
peer->incoming);
peer->incoming,
false);
}
static struct io_plan *peer_init_hdr_received(struct io_conn *conn,