Skip to content

Commit 83d28d8

Browse files
committed
Fix (and DRY) the conditionals before calling peer_disconnected
If we have a peer that sends a non-`Init` first message, we'll call `peer_disconnected` without ever having called `peer_connected` (which has to wait until we have an `Init` message). This is a violation of our API guarantees, though should generally not be an issue. Because this bug was repeated in a few places, we also take this opportunity to DRY up the logic which checks the peer state before calling `peer_disconnected`. Found by the new `ChannelManager` assertions and the `full_stack_target` fuzzer.
1 parent 2edb3f1 commit 83d28d8

File tree

1 file changed

+40
-31
lines changed

1 file changed

+40
-31
lines changed

lightning/src/ln/peer_handler.rs

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,11 @@ struct Peer {
393393
/// We cache a `NodeId` here to avoid serializing peers' keys every time we forward gossip
394394
/// messages in `PeerManager`. Use `Peer::set_their_node_id` to modify this field.
395395
their_node_id: Option<(PublicKey, NodeId)>,
396+
/// The features provided in the peer's [`msgs::Init`] message.
397+
///
398+
/// This is set only after we've processed the [`msgs::Init`] message and called relevant
399+
/// `peer_connected` handler methods. Thus, this field is set *iff* we've finished our
400+
/// handshake and can talk to this peer normally.
396401
their_features: Option<InitFeatures>,
397402
their_net_address: Option<NetAddress>,
398403

@@ -1877,24 +1882,21 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
18771882
// thread can be holding the peer lock if we have the global write
18781883
// lock).
18791884

1880-
if let Some(mut descriptor) = self.node_id_to_descriptor.lock().unwrap().remove(&node_id) {
1885+
let descriptor_opt = self.node_id_to_descriptor.lock().unwrap().remove(&node_id);
1886+
if let Some(mut descriptor) = descriptor_opt {
18811887
if let Some(peer_mutex) = peers.remove(&descriptor) {
1888+
let mut peer = peer_mutex.lock().unwrap();
18821889
if let Some(msg) = msg {
18831890
log_trace!(self.logger, "Handling DisconnectPeer HandleError event in peer_handler for node {} with message {}",
18841891
log_pubkey!(node_id),
18851892
msg.data);
1886-
let mut peer = peer_mutex.lock().unwrap();
18871893
self.enqueue_message(&mut *peer, &msg);
18881894
// This isn't guaranteed to work, but if there is enough free
18891895
// room in the send buffer, put the error message there...
18901896
self.do_attempt_write_data(&mut descriptor, &mut *peer, false);
1891-
} else {
1892-
log_trace!(self.logger, "Handling DisconnectPeer HandleError event in peer_handler for node {} with no message", log_pubkey!(node_id));
18931897
}
1898+
self.do_disconnect(descriptor, &*peer, "DisconnectPeer HandleError");
18941899
}
1895-
descriptor.disconnect_socket();
1896-
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
1897-
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
18981900
}
18991901
}
19001902
}
@@ -1905,6 +1907,22 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
19051907
self.disconnect_event_internal(descriptor, false);
19061908
}
19071909

1910+
fn do_disconnect(&self, mut descriptor: Descriptor, peer: &Peer, reason: &'static str) {
1911+
if peer.their_features.is_none() {
1912+
log_trace!(self.logger, "Disconnecting peer which hasn't completed handshake due to {}", reason);
1913+
descriptor.disconnect_socket();
1914+
return;
1915+
}
1916+
1917+
debug_assert!(peer.their_node_id.is_some());
1918+
if let Some((node_id, _)) = peer.their_node_id {
1919+
log_trace!(self.logger, "Disconnecting peer with id {} due to {}", node_id, reason);
1920+
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
1921+
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
1922+
}
1923+
descriptor.disconnect_socket();
1924+
}
1925+
19081926
fn disconnect_event_internal(&self, descriptor: &Descriptor, no_connection_possible: bool) {
19091927
let mut peers = self.peers.write().unwrap();
19101928
let peer_option = peers.remove(descriptor);
@@ -1916,6 +1934,8 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
19161934
},
19171935
Some(peer_lock) => {
19181936
let peer = peer_lock.lock().unwrap();
1937+
if peer.their_features.is_none() { return; }
1938+
debug_assert!(peer.their_node_id.is_some());
19191939
if let Some((node_id, _)) = peer.their_node_id {
19201940
log_trace!(self.logger,
19211941
"Handling disconnection of peer {}, with {}future connection to the peer possible.",
@@ -1937,14 +1957,13 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
19371957
/// peer. Thus, be very careful about reentrancy issues.
19381958
///
19391959
/// [`disconnect_socket`]: SocketDescriptor::disconnect_socket
1940-
pub fn disconnect_by_node_id(&self, node_id: PublicKey, no_connection_possible: bool) {
1960+
pub fn disconnect_by_node_id(&self, node_id: PublicKey, _no_connection_possible: bool) {
19411961
let mut peers_lock = self.peers.write().unwrap();
1942-
if let Some(mut descriptor) = self.node_id_to_descriptor.lock().unwrap().remove(&node_id) {
1943-
log_trace!(self.logger, "Disconnecting peer with id {} due to client request", node_id);
1944-
peers_lock.remove(&descriptor);
1945-
self.message_handler.chan_handler.peer_disconnected(&node_id, no_connection_possible);
1946-
self.message_handler.onion_message_handler.peer_disconnected(&node_id, no_connection_possible);
1947-
descriptor.disconnect_socket();
1962+
if let Some(descriptor) = self.node_id_to_descriptor.lock().unwrap().remove(&node_id) {
1963+
let peer_opt = peers_lock.remove(&descriptor);
1964+
if let Some(peer_mutex) = peer_opt {
1965+
self.do_disconnect(descriptor, &*peer_mutex.lock().unwrap(), "client request");
1966+
} else { debug_assert!(false, "node_id_to_descriptor thought we had a peer"); }
19481967
}
19491968
}
19501969

@@ -1955,13 +1974,8 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
19551974
let mut peers_lock = self.peers.write().unwrap();
19561975
self.node_id_to_descriptor.lock().unwrap().clear();
19571976
let peers = &mut *peers_lock;
1958-
for (mut descriptor, peer) in peers.drain() {
1959-
if let Some((node_id, _)) = peer.lock().unwrap().their_node_id {
1960-
log_trace!(self.logger, "Disconnecting peer with id {} due to client request to disconnect all peers", node_id);
1961-
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
1962-
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
1963-
}
1964-
descriptor.disconnect_socket();
1977+
for (descriptor, peer_mutex) in peers.drain() {
1978+
self.do_disconnect(descriptor, &*peer_mutex.lock().unwrap(), "client request to disconnect all peers");
19651979
}
19661980
}
19671981

@@ -2052,21 +2066,16 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
20522066
if !descriptors_needing_disconnect.is_empty() {
20532067
{
20542068
let mut peers_lock = self.peers.write().unwrap();
2055-
for descriptor in descriptors_needing_disconnect.iter() {
2056-
if let Some(peer) = peers_lock.remove(descriptor) {
2057-
if let Some((node_id, _)) = peer.lock().unwrap().their_node_id {
2058-
log_trace!(self.logger, "Disconnecting peer with id {} due to ping timeout", node_id);
2069+
for descriptor in descriptors_needing_disconnect.drain(..) {
2070+
if let Some(peer_mutex) = peers_lock.remove(&descriptor) {
2071+
let peer = peer_mutex.lock().unwrap();
2072+
if let Some((node_id, _)) = peer.their_node_id {
20592073
self.node_id_to_descriptor.lock().unwrap().remove(&node_id);
2060-
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
2061-
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
20622074
}
2075+
self.do_disconnect(descriptor, &*peer, "ping timeout");
20632076
}
20642077
}
20652078
}
2066-
2067-
for mut descriptor in descriptors_needing_disconnect.drain(..) {
2068-
descriptor.disconnect_socket();
2069-
}
20702079
}
20712080
}
20722081

0 commit comments

Comments
 (0)