Skip to content

Conversation

@ajweiss
Copy link
Contributor

@ajweiss ajweiss commented Dec 18, 2014

This is a regression in 0.10 that does not appear in 0.9.x.

vBlocksInFlight, mapBlocksInFlight and friends can be remotely inflated by supplying an excessive number of block inv messages with garbage hashes. In my local testing, it took about 10 minutes to pump in 1GB of bad inv messages, resulting in 6GB of memory usage and 30GB of outbound getheaders data from bitcoind. After a malicious client disconnects, the memory may be reused, but does not appear to be released back to the operating system.

The 0.9.x code started applying a 10 point ban penalty at 5000 blocks in flight leading to a ban at 5010 , while under headers first we shouldn't see more than 16. It's probably good to have some headroom to prevent buggy or older software from getting banned, but the numbers here are just reasonable guesstimates.

I don't like fixed constants, and while MAX_DOWNLOADS_PER_PEER seems to make sense here, I like the idea of leaving some headroom. This bumps it down to 2000 blocks and uses an existing constant that won't be changing soon.

This will probably be superceded by #4831, or something built upon it, but a patch for 0.10 seems prudent.

I've tested by sync'ing from genesis, and multiple runs catching up tip-48h to tip. No problems were observed.

@laanwj laanwj added this to the 0.10.0 milestone Dec 19, 2014
@laanwj
Copy link
Member

laanwj commented Dec 19, 2014

Thanks, good catch, assigned 0.10 milestone.

utACK

@sipa
Copy link
Member

sipa commented Dec 19, 2014

Nice catch, this is indeed a problem.

I'm less sure about the solution. MarkBlockAsInFlight is only called as a result of a local decision to start fetching a block, so if it overflows, it just means the logic for decision to download blocks in the first place is wrong.

So, there are two possible code paths that lead to a decision to download a block. One is the 'normal' headers-based synchronization: see the FindNextBlocksToDownload() call in main.cpp:SendMessages. This one should properly take the number of blocks in flight into account, and can always function as a fallback.

The other is the 'direct download' optimized path, in the "inv" handling in main.cppProcessMessage, which only works in the case we assume we're already very close to syncing, and is there to reduce latency in waiting for SendMessages, plus avoids a roundtrip between asking the headers and asking the block.

I think the solution is just disabling the second mechanism in case we're already downloading too many blocks from the peer under consideration. We shouldn't look at the total number in flight for this, though, as that would lead to a potential DoS where a few peers spam block announcements, and avoid using the optimized fetching from honest peers.

@sipa
Copy link
Member

sipa commented Dec 19, 2014

Also, #4831 is only affects transaction fetching, not block fetching, so a solution is very welcome here, including master.

@ajweiss
Copy link
Contributor Author

ajweiss commented Dec 19, 2014

Cool! I've reverted the original strategy... I assume you mean something like this. I've verified that it does indeed stop the attack and I'm playing with testing synchronization under a few conditions now.

@sipa
Copy link
Member

sipa commented Dec 22, 2014

Untested ACK (after squash). Testing on testnet now.

@sipa
Copy link
Member

sipa commented Dec 22, 2014

Tested ACK.

@ajweiss
Copy link
Contributor Author

ajweiss commented Dec 22, 2014

afk today, will squash tonight... also tested against bogus inv floods and early/late stage sync...

Don't allow immediate inv driven block downloads if
a peer already has MAX_BLOCKS_IN_TRANSIT_PER_PEER
active downloads.  Prevents bogus inv spam from
blowing up block transfer tracking data structures.
@ajweiss ajweiss force-pushed the ajw_1412_bound_inflight_data branch from a81e06e to c907704 Compare December 23, 2014 07:25
@ajweiss
Copy link
Contributor Author

ajweiss commented Dec 23, 2014

Rebase-squashed. No changes from what sipa tested.

@btcdrak
Copy link
Contributor

btcdrak commented Dec 23, 2014

utACK. code is the same after squash.

nicely found @ajweiss

@gmaxwell
Copy link
Contributor

ACK.

@laanwj laanwj merged commit c907704 into bitcoin:master Dec 23, 2014
laanwj added a commit that referenced this pull request Dec 23, 2014
c907704 DOS: Respect max per-peer blocks in flight limit (Adam Weiss)
laanwj pushed a commit that referenced this pull request Dec 23, 2014
Don't allow immediate inv driven block downloads if
a peer already has MAX_BLOCKS_IN_TRANSIT_PER_PEER
active downloads.  Prevents bogus inv spam from
blowing up block transfer tracking data structures.

Rebased-From: c907704
Github-Pull: #5507
reddink pushed a commit to reddcoin-project/reddcoin-3.10 that referenced this pull request Jul 11, 2020
Don't allow immediate inv driven block downloads if
a peer already has MAX_BLOCKS_IN_TRANSIT_PER_PEER
active downloads.  Prevents bogus inv spam from
blowing up block transfer tracking data structures.

Rebased-From: c907704
Github-Pull: bitcoin#5507
(cherry picked from commit d10a901)
reddink pushed a commit to reddcoin-project/reddcoin-3.10 that referenced this pull request Jul 14, 2020
Don't allow immediate inv driven block downloads if
a peer already has MAX_BLOCKS_IN_TRANSIT_PER_PEER
active downloads.  Prevents bogus inv spam from
blowing up block transfer tracking data structures.

Rebased-From: c907704
Github-Pull: bitcoin#5507
(cherry picked from commit d10a901)
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants