Skip to content

Commit 2f6f7ce

Browse files
authored
Merge pull request #1472 from tomt1664/fix_race_condition
net: fix race condition in self-connect detection
2 parents 67cd78d + 8db506f commit 2f6f7ce

File tree

3 files changed

+21
-9
lines changed

3 files changed

+21
-9
lines changed

src/net.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ class NetEventsInterface
727727
{
728728
public:
729729
/** Initialize a peer (setup state, queue any initial messages) */
730-
virtual void InitializeNode(CNode* pnode) = 0;
730+
virtual void InitializeNode(const CNode* pnode) = 0;
731731

732732
/** Handle removal of a peer (clear state) */
733733
virtual void FinalizeNode(const CNode& node) = 0;

src/net_processing.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ struct Peer {
222222
* Most peers use headers-first syncing, which doesn't use this mechanism */
223223
uint256 m_continuation_block GUARDED_BY(m_block_inv_mutex) {};
224224

225+
Mutex m_msgproc_mutex;
226+
/** Set to true once initial VERSION message was sent (only relevant for outbound peers). */
227+
bool m_outbound_version_message_sent GUARDED_BY(m_msgproc_mutex){false};
228+
225229
/** This peer's reported block height when we connected */
226230
std::atomic<int> m_starting_height{-1};
227231

@@ -312,7 +316,7 @@ class PeerManagerImpl final : public PeerManager
312316
void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) override;
313317

314318
/** Implement NetEventsInterface */
315-
void InitializeNode(CNode* pnode) override;
319+
void InitializeNode(const CNode* pnode) override;
316320
void FinalizeNode(const CNode& node) override;
317321
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override;
318322
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
@@ -1189,7 +1193,7 @@ void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)
11891193
if (state) state->m_last_block_announcement = time_in_seconds;
11901194
}
11911195

1192-
void PeerManagerImpl::InitializeNode(CNode *pnode)
1196+
void PeerManagerImpl::InitializeNode(const CNode *pnode)
11931197
{
11941198
NodeId nodeid = pnode->GetId();
11951199
{
@@ -1202,9 +1206,6 @@ void PeerManagerImpl::InitializeNode(CNode *pnode)
12021206
LOCK(m_peer_mutex);
12031207
m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer));
12041208
}
1205-
if (!pnode->IsInboundConn()) {
1206-
PushNodeVersion(*pnode);
1207-
}
12081209
}
12091210

12101211
void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler)
@@ -4201,6 +4202,10 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt
42014202
PeerRef peer = GetPeerRef(pfrom->GetId());
42024203
if (peer == nullptr) return false;
42034204

4205+
// For outbound connections, ensure that the initial VERSION message
4206+
// has been sent first before processing any incoming messages
4207+
if (!pfrom->IsInboundConn() && WITH_LOCK(peer->m_msgproc_mutex, return !peer->m_outbound_version_message_sent)) return false;
4208+
42044209
{
42054210
LOCK(peer->m_getdata_requests_mutex);
42064211
if (!peer->m_getdata_requests.empty()) {
@@ -4660,6 +4665,13 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
46604665
// disconnect misbehaving peers even before the version handshake is complete.
46614666
if (MaybeDiscourageAndDisconnect(*pto, *peer)) return true;
46624667

4668+
// Initiate version handshake for outbound connections
4669+
if (!pto->IsInboundConn() && WITH_LOCK(peer->m_msgproc_mutex, return !peer->m_outbound_version_message_sent)) {
4670+
LOCK(peer->m_msgproc_mutex);
4671+
PushNodeVersion(*pto);
4672+
peer->m_outbound_version_message_sent = true;
4673+
}
4674+
46634675
// Don't send anything until the version handshake is complete
46644676
if (!pto->fSuccessfullyConnected || pto->fDisconnect)
46654677
return true;

src/test/fuzz/util.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,13 @@ void FillNode(FuzzedDataProvider& fuzzed_data_provider, ConnmanTestMsg& connman,
244244
filter_txs),
245245
};
246246

247-
(void)connman.ReceiveMsgFrom(node, msg_version);
248-
node.fPauseSend = false;
249-
connman.ProcessMessagesOnce(node);
250247
{
251248
LOCK(node.cs_sendProcessing);
252249
peerman.SendMessages(&node);
253250
}
251+
(void)connman.ReceiveMsgFrom(node, msg_version);
252+
node.fPauseSend = false;
253+
connman.ProcessMessagesOnce(node);
254254
if (node.fDisconnect) return;
255255
assert(node.nVersion == version);
256256
assert(node.GetCommonVersion() == std::min(version, PROTOCOL_VERSION));

0 commit comments

Comments
 (0)