sipa / bitcoin

Bitcoin integration/staging tree

Home Page:http://www.bitcoin.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DoS: cause segnet4 bitcoind to core dump

opened this issue · comments

This is from a build from segwit-master, commit e82f2fc, which I can't seem to find now but it was fairly recent, probably from the end of May.

I will rebuild bitcoind from more recent source tonight to see if this crash is there in the latest -- by the way what's the branch I should build? There's about 8 segwit branches 😄

I have my own weird SPV client code which I'm writing, which almost certainly doesn't properly follow the wire protocol and sends the wrong things. But that still shouldn't crash bitcoind.

It seems to be related to merkle-block sending which I believe is in an unfinished state, so this may be a bug that's already known, or related to unfinished code in this branch. Anyways, figured I'd post it in case it was something new.

Here's all the debug log I can get

2016-06-07 05:51:57 Added connection peer=3
2016-06-07 05:51:57 connection from 127.0.0.1:41806 accepted
2016-06-07 05:51:57 received: version (111 bytes) peer=3
2016-06-07 05:51:57 send version message: version 70013, blocks=33845, us=555.555.555.555:28901, peer=3
2016-06-07 05:51:57 sending: version (103 bytes) peer=3
2016-06-07 05:51:57 sending: verack (0 bytes) peer=3
2016-06-07 05:51:57 receive version message: /btcwire:0.4.0/test:zero/: version 70012, blocks=0, us=10.0.0.11:28900, peer=3
2016-06-07 05:51:57 added time data, samples 4, offset +0 (+0 minutes)
2016-06-07 05:51:57 sending: ping (8 bytes) peer=3
2016-06-07 05:51:57 AdvertiseLocal: advertising address 555.555.555.555:28901
2016-06-07 05:51:57 sending: addr (31 bytes) peer=3
2016-06-07 05:51:58 received: verack (0 bytes) peer=3
2016-06-07 05:51:58 sending: sendheaders (0 bytes) peer=3
2016-06-07 05:51:58 received: getheaders (69 bytes) peer=3
2016-06-07 05:51:58 getheaders -1 to 0000000000000000000000000000000000000000000000000000000000000000 from peer=3
2016-06-07 05:51:58 sending: headers (1 bytes) peer=3
2016-06-07 05:51:58 received: pong (8 bytes) peer=3
2016-06-07 05:51:58 received: filterload (53 bytes) peer=3
2016-06-07 05:51:58 received: getdata (37 bytes) peer=3
2016-06-07 05:51:58 received getdata (1 invsz) peer=3
2016-06-07 05:51:58 received getdata for: merkleblock 000000005c83f6e456ea6137edaa2ec962166ab65d9dc90c607dee97a766acbb peer=3
2016-06-07 05:51:58 sending: merkleblock (119 bytes) peer=3
2016-06-07 05:51:58 received: getdata (37 bytes) peer=3
2016-06-07 05:51:58 received getdata (1 invsz) peer=3
2016-06-07 05:51:58 received getdata for: merkleblock 00000000511278eb2ce6d3e258fd934cd1a6853eb5eb1e6f48307e2ad3206b37 peer=3
2016-06-07 05:51:58 sending: merkleblock (119 bytes) peer=3
2016-06-07 05:51:58 received: getdata (37 bytes) peer=3
2016-06-07 05:51:58 received getdata (1 invsz) peer=3
2016-06-07 05:51:58 received getdata for: merkleblock 00000000563f93e8d2d2112ccd5b5f9746cf845acd1eeddc79504ee9fad6b222 peer=3
2016-06-07 05:51:58 sending: merkleblock (119 bytes) peer=3
2016-06-07 05:51:58 received: getdata (37 bytes) peer=3
2016-06-07 05:51:58 received getdata (1 invsz) peer=3
2016-06-07 05:51:58 received getdata for: merkleblock 000001288edd8dd50fc5c32fc55d127490395b3e5c5684e46eca35244130c6ee peer=3
2016-06-07 05:51:58 sending: merkleblock (506 bytes) peer=3
2016-06-07 05:51:58 sending: tx

doesn't actually finish the last line, do there's no newline there. I get
Aborted (core dumped) nohup ./bitcoind
on the terminal.

On the client side, I actually get some txs that don't make it into the debug.log:

dbTip 33517 headerTip 33845
will request blocks 33518 to 33845
made 12 element filter
sent filter df50e2271a5af6047e692002974b6089dc5df093624009da27e424e7c3d87c1fd5d165c129fb1c345b500b
2016/06/06 22:51:58 added b60c75e89e03470ae7427c5a004830c26ba87ef3dae0c8abf1641a430adce7b7 to OKTxids at height 33521
2016/06/06 22:51:58 added 41dc9bee24a337c8818f6612ad8ce03b080d1b20accab3e5d87a186e1143a7ab to OKTxids at height 33521
2016/06/06 22:51:58 added e882be68c5c64939d927cf223866402d5d4f218452810693b82f4ccdc12aa293 to OKTxids at height 33521
2016/06/06 22:51:58 added d50add9db38577ef77fbb2d978e17ead624fc8b98bf008027a31567eeeffb434 to OKTxids at height 33521
2016/06/06 22:51:58 added feab64515571f20161341615e7e26fae217a510b1b8f9d3739f832a6ffcffc27 to OKTxids at height 33521
2016/06/06 22:51:58 ReadMessageWithEncodingN error.  Disconnecting: EOF

This is not bitcoind, it's a btcd based SPV client; probably clear enough what's going on -- it sends a filter, requests blocks, and then gets 5 txs from block 000001288e before the TCP connection dies.

I'll build newer code, though it takes ~1hr for me to build so will test tomorrow.
Hope this helps

I guess technically it's tomorrow now :)

with commit 17389dc, it seems to work fine.
Same SPV client connecting:

2016-06-07 07:11:17 received: getdata (37 bytes) peer=12
2016-06-07 07:11:17 received getdata (1 invsz) peer=12
2016-06-07 07:11:17 received getdata for: merkleblock 000000003ddd36873fa97fc093cc1716e573f96973d56d21fbdf87a1a7024668 peer=12
2016-06-07 07:11:17 sending: merkleblock (119 bytes) peer=12
2016-06-07 07:11:17 received: getdata (37 bytes) peer=12
2016-06-07 07:11:17 received getdata (1 invsz) peer=12
2016-06-07 07:11:17 received getdata for: merkleblock 00000000230cadd1b7978df64c07f945bbe289fc1f2c43eb6fbfa466f7c3d0e3 peer=12
2016-06-07 07:11:17 sending: merkleblock (119 bytes) peer=12
2016-06-07 07:11:17 received: filterload (56 bytes) peer=12
2016-06-07 07:11:17 received: getdata (37 bytes) peer=12
2016-06-07 07:11:17 received getdata (1 invsz) peer=12
2016-06-07 07:11:17 received getdata for: merkleblock 0000000057d2496638cc26f199ba99ff9c7d160438ad096e900bf5f83ac330b8 peer=12
2016-06-07 07:11:17 sending: merkleblock (119 bytes) peer=12
2016-06-07 07:11:17 received: getdata (37 bytes) peer=12
2016-06-07 07:11:17 received getdata (1 invsz) peer=12
2016-06-07 07:11:17 received getdata for: merkleblock 0000013895b5c8579e04e97c6d5f8f557873e2a17519d8a4891b8a296875ce6a peer=12
2016-06-07 07:11:17 sending: merkleblock (473 bytes) peer=12
2016-06-07 07:11:17 sending: tx (549 bytes) peer=12
2016-06-07 07:11:17 sending: tx (223 bytes) peer=12
2016-06-07 07:11:17 sending: tx (698 bytes) peer=12
2016-06-07 07:11:17 sending: tx (222 bytes) peer=12
2016-06-07 07:11:17 sending: tx (254 bytes) peer=12
2016-06-07 07:11:17 received: getdata (37 bytes) peer=12
2016-06-07 07:11:17 received getdata (1 invsz) peer=12
2016-06-07 07:11:17 received getdata for: merkleblock 0000007facb224b1de4d96857d6760b93d3843d294d07a6c8f6229e3eb351ebb peer=12
2016-06-07 07:11:17 sending: merkleblock (119 bytes) peer=12
2016-06-07 07:11:17 received: getdata (37 bytes) peer=12
2016-06-07 07:11:17 received getdata (1 invsz) peer=12
2016-06-07 07:11:17 received getdata for: merkleblock 00000171463a3bd5b5f16051699811e6e8533ce822ea9d2e422147c704e27239 peer=12
2016-06-07 07:11:17 sending: merkleblock (119 bytes) peer=12
2016-06-07 07:11:17 received: getdata (37 bytes) peer=12
2016-06-07 07:11:17 received getdata (1 invsz) peer=12

...etc

So I guess it's OK; I don't know what code changed but seems fine. I can close this issue; might be helpful to keep track if this kind of thing even shows up.

Some more searching for the cause of this

I'm actually a little confused with the git stuff as it's rather complex; some of the commits I build don't support segnet4... anyway I built at commit 7b539f9, and got similar behavior, but no crash. This is maybe helpful as it logs errors:

2016-06-07 17:49:45 getheaders 32001 to 0000000000000000000000000000000000000000000000000000000000000000 from peer=2
2016-06-07 17:49:45 sending: headers (152850 bytes) peer=2
2016-06-07 17:49:45 received: getheaders (69 bytes) peer=2
2016-06-07 17:49:45 getheaders -1 to 0000000000000000000000000000000000000000000000000000000000000000 from peer=2
2016-06-07 17:49:45 sending: headers (1 bytes) peer=2
2016-06-07 17:49:46 received: filterload (13 bytes) peer=2
2016-06-07 17:49:46 received: getdata (37 bytes) peer=2
2016-06-07 17:49:46 received getdata (1 invsz) peer=2
2016-06-07 17:49:46 

************************
EXCEPTION: St12out_of_range       
CInv::GetCommand(): type=3 unknown type       
bitcoin in ProcessMessages()       

2016-06-07 17:49:46 ProcessMessages(getdata, 37 bytes) FAILED peer=2
2016-06-07 17:49:46 received: getdata (37 bytes) peer=2
2016-06-07 17:49:46 received getdata (1 invsz) peer=2
2016-06-07 17:49:46 

************************
EXCEPTION: St12out_of_range       
CInv::GetCommand(): type=3 unknown type       
bitcoin in ProcessMessages()       

2016-06-07 17:49:46 ProcessMessages(getdata, 37 bytes) FAILED peer=2
2016-06-07 17:49:46 received: getdata (37 bytes) peer=2
2016-06-07 17:49:46 received getdata (1 invsz) peer=2
2016-06-07 17:49:46 

************************
EXCEPTION: St12out_of_range       
CInv::GetCommand(): type=3 unknown type       
bitcoin in ProcessMessages()       

2016-06-07 17:49:46 ProcessMessages(getdata, 37 bytes) FAILED peer=2
2016-06-07 17:49:46 received: getdata (37 bytes) peer=2
2016-06-07 17:49:46 received getdata (1 invsz) peer=2
2016-06-07 17:49:46 

this error repeats maybe 20 times. Hm I should count.
OK it repeats 32 times. Which is a nice computery number :)

But this build doesn't crash. On the SPV client side I see:

dbTip 33500 headerTip 33887
will request blocks 33501 to 33887
made 23 element filter
sent filter c5c3902a516aa1ae9f5c6273e802da030746d78a632ef20fa47532497802e0ab03ffd3136ad163a03c556865263ce270dc7a7897bc24e569f80bf255150f9b386581fb046b41dbd496dc62027de3708dfc67
^C

it hangs after sending the filter and requesting the first merkle block. TCP connection doesn't close though so I break manually.

Anyway in the current and more recent builds it seems this problem is solved? So maybe it's OK. But I can try other commits in the last month to see where the problem changed or git fixed.

@T909 I think this non-crash at 7b539f9 is not helpful, because at that point there was a bug in CInv::GetCommand that wasn't fixed until 97d7402, a commit that was included in e82f2fc. So if I understand correctly, you're basically triggering a different bug that would occur before the bug you stumbled upon in your original post.

On IRC @sdaftuar isolated the problem: At commit e82f2fc, main.cpp line

pfrom->PushMessage(NetMsgType::TX, block.vtx[pair.first]);

didn't specify witness or non-witness transactions to send.

If you change that line from
pfrom->PushMessage(NetMsgType::TX, block.vtx[pair.first]);
to
pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, block.vtx[pair.first]);

then everything works OK -- no crashes, the SPV client gets all the merkle blocks and transactions.
As the problem is isolated & fixed (and was fixed in more recent commits anyway), I'll close the issue.
Thanks to @sdaftuar and @sipa for the help!