Skip to content

Commit 311e69d

Browse files
committed
Ban peer race condition (#4140)
It is possible that when we go to ban a peer, there is already an unbanned message in the queue. It could lead to the case that we ban and immediately unban a peer leaving us in a state where a should-be banned peer is unbanned. If this banned peer connects to us in this faulty state, we currently do not attempt to re-ban it. This PR does correct this also, so if we do see this error, it will now self-correct (although we shouldn't see the error in the first place). I have also incremented the severity of not supporting protocols as I see peers ultimately get banned in a few steps and it seems to make sense to just ban them outright, rather than have them linger.
1 parent e2c68c8 commit 311e69d

File tree

3 files changed

+20
-9
lines changed

3 files changed

+20
-9
lines changed

beacon_node/lighthouse_network/src/peer_manager/mod.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,20 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
290290

291291
// If a peer is being banned, this trumps any temporary ban the peer might be
292292
// under. We no longer track it in the temporary ban list.
293-
self.temporary_banned_peers.raw_remove(peer_id);
294-
295-
// Inform the Swarm to ban the peer
296-
self.events
297-
.push(PeerManagerEvent::Banned(*peer_id, banned_ips));
293+
if !self.temporary_banned_peers.raw_remove(peer_id) {
294+
// If the peer is not already banned, inform the Swarm to ban the peer
295+
self.events
296+
.push(PeerManagerEvent::Banned(*peer_id, banned_ips));
297+
// If the peer was in the process of being un-banned, remove it (a rare race
298+
// condition)
299+
self.events.retain(|event| {
300+
if let PeerManagerEvent::UnBanned(unbanned_peer_id, _) = event {
301+
unbanned_peer_id != peer_id // Remove matching peer ids
302+
} else {
303+
true
304+
}
305+
});
306+
}
298307
}
299308
}
300309
}
@@ -552,8 +561,8 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
552561
Protocol::BlocksByRoot => return,
553562
Protocol::Goodbye => return,
554563
Protocol::LightClientBootstrap => return,
555-
Protocol::MetaData => PeerAction::LowToleranceError,
556-
Protocol::Status => PeerAction::LowToleranceError,
564+
Protocol::MetaData => PeerAction::Fatal,
565+
Protocol::Status => PeerAction::Fatal,
557566
}
558567
}
559568
RPCError::StreamTimeout => match direction {

beacon_node/lighthouse_network/src/peer_manager/network_behaviour.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,10 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
156156
BanResult::BadScore => {
157157
// This is a faulty state
158158
error!(self.log, "Connected to a banned peer. Re-banning"; "peer_id" => %peer_id);
159-
// Reban the peer
159+
// Disconnect the peer.
160160
self.goodbye_peer(&peer_id, GoodbyeReason::Banned, ReportSource::PeerManager);
161+
// Re-ban the peer to prevent repeated errors.
162+
self.events.push(PeerManagerEvent::Banned(peer_id, vec![]));
161163
return;
162164
}
163165
BanResult::BannedIp(ip_addr) => {

beacon_node/lighthouse_network/src/service/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
11191119
debug!(self.log, "Peer does not support gossipsub"; "peer_id" => %peer_id);
11201120
self.peer_manager_mut().report_peer(
11211121
&peer_id,
1122-
PeerAction::LowToleranceError,
1122+
PeerAction::Fatal,
11231123
ReportSource::Gossipsub,
11241124
Some(GoodbyeReason::Unknown),
11251125
"does_not_support_gossipsub",

0 commit comments

Comments
 (0)