Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

p2p: Move all header verification into the network layer, extend logging #19107

Merged
merged 6 commits into from Sep 29, 2020

Conversation

troygiorshev
Copy link
Contributor

Inspired by #15206 and #15197, this PR moves all message header verification from the message processing layer and into the network/transport layer.

In the previous PRs there is a change in behavior, where we would disconnect from peers upon a single failed checksum check. In various discussions there was concern over whether this was the right choice, and some expressed a desire to see how this would look if it was made to be a pure refactor.

For more context, see https://bitcoincore.reviews/15206.html#l-81.

This PR improves the separation between the p2p layers, helping improvements like BIP324 and #18989.

@maflcko maflcko removed the Tests label May 29, 2020
@troygiorshev troygiorshev force-pushed the p2p-refactor-header branch 2 times, most recently from 821f4af to 800e56c Compare May 29, 2020 16:28
@DrahtBot
Copy link
Contributor

DrahtBot commented May 29, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

src/net.cpp Outdated Show resolved Hide resolved
@jnewbery
Copy link
Contributor

Concept ACK

@maflcko
Copy link
Member

maflcko commented Jun 1, 2020

Run p2p_transport_deserializer with args ['/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer', '-runs=1', '/home/travis/build/bitcoin/bitcoin/ci/scratch/qa-assets/fuzz_seed_corpus/p2p_transport_deserializer']INFO: Seed: 2855084377

INFO: Loaded 1 modules   (412040 inline 8-bit counters): 412040 [0x560bb09480d8, 0x560bb09aca60), 

INFO: Loaded 1 PC tables (412040 PCs): 412040 [0x560bb09aca60,0x560bb0ff62e0), 

INFO:      128 files found in /home/travis/build/bitcoin/bitcoin/ci/scratch/qa-assets/fuzz_seed_corpus/p2p_transport_deserializer

INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 1048576 bytes

INFO: seed corpus: files: 128 min: 1b max: 1048576b total: 8594313b rss: 88Mb

p2p_transport_deserializer: test/fuzz/p2p_transport_deserializer.cpp:35: void test_one_input(const std::vector<uint8_t> &): Assertion `result' failed.

==31678== ERROR: libFuzzer: deadly signal

    #0 0x560bae1f1881 in __sanitizer_print_stack_trace (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x198a881)

    #1 0x560bae13c9d8 in fuzzer::PrintStackTrace() (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x18d59d8)

    #2 0x560bae121b23 in fuzzer::Fuzzer::CrashCallback() (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x18bab23)

    #3 0x7f38b4a473bf  (/lib/x86_64-linux-gnu/libpthread.so.0+0x153bf)

    #4 0x7f38b46ae18a in raise (/lib/x86_64-linux-gnu/libc.so.6+0x4618a)

    #5 0x7f38b468d858 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x25858)

    #6 0x7f38b468d728  (/lib/x86_64-linux-gnu/libc.so.6+0x25728)

    #7 0x7f38b469ef35 in __assert_fail (/lib/x86_64-linux-gnu/libc.so.6+0x36f35)

    #8 0x560bae21b71f in test_one_input(std::vector<unsigned char, std::allocator<unsigned char> > const&) /home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer.cpp:35:13

    #9 0x560baf33d9e1 in LLVMFuzzerTestOneInput /home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/fuzz.cpp:36:5

    #10 0x560bae1231e1 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x18bc1e1)

    #11 0x560bae122925 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x18bb925)

    #12 0x560bae125247 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x18be247)

    #13 0x560bae1255a9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x18be5a9)

    #14 0x560bae11427e in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x18ad27e)

    #15 0x560bae13d0c2 in main (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x18d60c2)

    #16 0x7f38b468f0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

    #17 0x560bae0e901d in _start (/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src/test/fuzz/p2p_transport_deserializer+0x188201d)

NOTE: libFuzzer has rudimentary signal handlers.

      Combine libFuzzer with AddressSanitizer or similar for better crash reports.

SUMMARY: libFuzzer: deadly signal

MS: 0 ; base unit: 0000000000000000000000000000000000000000

0xfa,0xbf,0xb5,0xda,0x40,0x6e,0x6e,0x6e,0x6e,0x7f,0x6f,0x3,0x34,0x64,0x6e,0x0,0x0,0x0,0x0,0x0,0x28,0xf6,0x6e,0x6e,

\xfa\xbf\xb5\xda@nnnn\x7fo\x034dn\x00\x00\x00\x00\x00(\xf6nn

artifact_prefix='./'; Test unit written to ./crash-fc30b01e02b9667a2f09968f8a88c869ab056464

Base64: +r+12kBubm5uf28DNGRuAAAAAAAo9m5u

Copy link
Contributor

@rajarshimaitra rajarshimaitra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK. Verified unit and functional tests are passing. Thanks for adding the doxy comment on ReceiveMsgBytes, that cleared some of my earlier doubts.
I found the commits to be a little difficult to parse as the same function is being changed in different commits. This can be good for demonstrating the stepwise changes, but in this case, it resulted in reviewing some lines which later got removed in later commits. So maybe a little consolidation of commits can help future review.
Overall strong concept ACK as this refactor has been discussed in review club and generally accepted as a good idea except the connection dropping behavior.
Below are few comments on the code which shows some probable scope of improvement.

src/net.cpp Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net_processing.cpp Show resolved Hide resolved
src/protocol.cpp Outdated Show resolved Hide resolved
src/protocol.cpp Outdated Show resolved Hide resolved
test/functional/p2p_invalid_messages.py Outdated Show resolved Hide resolved
Copy link
Contributor

@jnewbery jnewbery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff so far @troygiorshev !

I try to format my commit logs as:

[component]: short summary (50 chars or less if possible)

Reason for the change (why not what or how) (wrapped at 72 or 80 columns)

See https://chris.beams.io/posts/git-commit/ for more tips on writing great commit logs.

src/protocol.h Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net.h Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net.h Outdated Show resolved Hide resolved
src/net.h Outdated Show resolved Hide resolved
src/protocol.h Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
test/functional/p2p_invalid_messages.py Outdated Show resolved Hide resolved
src/test/fuzz/deserialize.cpp Show resolved Hide resolved
@troygiorshev
Copy link
Contributor Author

Rebased, fixed failing fuzz tests. Removed some of the unneeded test changes, they're now in #19177. Overall the commits are cleaned up. They are all atomic now, with full commit messages. I've also implemented many of the suggestions, thanks again to everyone for the review so far!

@troygiorshev
Copy link
Contributor Author

troygiorshev commented Sep 16, 2020

git range-diff master 367bb95 ead6393

  • s/out_err/out_err_raw_size/ in all spots except for the single prototype in TransportDeserializer

@troygiorshev
Copy link
Contributor Author

Thanks for the review @jonatack and @ryanofsky!

I'm going to leave the suggestions for a follow-up PR. As it stands, this PR has three ACKs from people experienced in this part of the codebase. I'd like to reduce the diff that they have to go through.

  • @jnewbery on 9377c0c. The following range-diffs may be useful
    • Rebase: git range-diff master 9377c0c e72c5b2
    • Rebase: git range-diff master e72c5b2 367bb95
    • Rename: git range-diff master 367bb95 ead6393
  • @dongcarl on e72c5b2
    • The rebase and rename immediately above this comment
  • @ryanofsky on e72c5b2
    • The rebase and rename immediately above this comment

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review ACK ead6393. Only changes since last review are rebase with vRecv/msg.m_recv conflict and renaming out_err to out_err_raw_size

This is intended to only be used for logging.

This will allow log messages in the following commits to keep recording
the peer's ID, even when logging is moved into V1TransportDeserializer.
This removes the m_valid_checksum member from CNetMessage.  Instead,
GetMessage() returns an Optional.

Additionally, GetMessage() has been given an out parameter to be used to
hold error information.  For now it is specifically a uint32_t used to
hold the raw size of the corrupt message.

The checksum check is now done in GetMessage.
This commit removes the single-parameter contructor of CMessageHeader
and replaces it with a default constructor.

The single parameter contructor isn't used anywhere except for tests.
There is no reason to initialize a CMessageHeader with a particular
messagestart.  This messagestart should always be replaced when
deserializing an actual message header so that we can run checks on it.

The default constructor initializes it to zero, just like the command
and checksum.

This also removes a parameter of a V1TransportDeserializer constructor,
as it was only used for this purpose.
This adds a CChainParams& member to V1TransportDeserializer member, and
use it in place of many Params() calls.  In addition to reducing the
number of calls to a global, this removes a parameter from GetMessage
(and will later allow us to remove one from CMessageHeader::IsValid())
This moves header size and netmagic checking out of net_processing and
into net.  This check now runs in ReadHeader, so that net can exit early
out of receiving bytes from the peer.  IsValid is now slimmed down, so
it no longer needs a MessageStartChars& parameter.

Additionally this removes the rest of the m_valid_* members from
CNetMessage.
@troygiorshev
Copy link
Contributor Author

git range-diff master ead6393 deb5271

Trivial rebase

@jnewbery
Copy link
Contributor

Code review ACK deb5271.

Should be ready for merge with a reACK from @dongcarl and @ryanofsky

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review ACK deb5271 just rebase due to conflict on adjacent line

@fanquake fanquake merged commit 6af9b31 into bitcoin:master Sep 29, 2020
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Sep 29, 2020
…rk layer, extend logging

deb5271 Remove header checks out of net_processing (Troy Giorshev)
52d4ae4 Give V1TransportDeserializer CChainParams& member (Troy Giorshev)
5bceef6 Change CMessageHeader Constructor (Troy Giorshev)
1ca20c1 Add doxygen comment for ReceiveMsgBytes (Troy Giorshev)
890b1d7 Move checksum check from net_processing to net (Troy Giorshev)
2716647 Give V1TransportDeserializer an m_node_id member (Troy Giorshev)

Pull request description:

  Inspired by bitcoin#15206 and bitcoin#15197, this PR moves all message header verification from the message processing layer and into the network/transport layer.

  In the previous PRs there is a change in behavior, where we would disconnect from peers upon a single failed checksum check.  In various discussions there was concern over whether this was the right choice, and some expressed a desire to see how this would look if it was made to be a pure refactor.

  For more context, see https://bitcoincore.reviews/15206.html#l-81.

  This PR improves the separation between the p2p layers, helping improvements like [BIP324](bitcoin#18242) and bitcoin#18989.

ACKs for top commit:
  ryanofsky:
    Code review ACK deb5271 just rebase due to conflict on adjacent line
  jnewbery:
    Code review ACK deb5271.

Tree-SHA512: 1a3b7ae883b020cfee1bef968813e04df651ffdad9dd961a826bd80654f2c98676ce7f4721038a1b78d8790e4cebe8060419e3d8affc97ce2b9b4e4b72e6fa9f
jnewbery pushed a commit to jnewbery/bitcoin that referenced this pull request Aug 18, 2021
Also, access mapRecvBytesPerMsgCmd with `at()` not `find()`. This
throws an error if COMMAND_OTHER doesn't exist, which should never
happen. `find()` instead just accessed the last element, which could make
debugging more difficult.

Resolves review comments from PR19107:

- bitcoin#19107 (comment)
- bitcoin#19107 (comment)
jnewbery pushed a commit to jnewbery/bitcoin that referenced this pull request Aug 19, 2021
Also, access mapRecvBytesPerMsgCmd with `at()` not `find()`. This
throws an error if COMMAND_OTHER doesn't exist, which should never
happen. `find()` instead just accessed the last element, which could make
debugging more difficult.

Resolves review comments from PR19107:

- bitcoin#19107 (comment)
- bitcoin#19107 (comment)
maflcko pushed a commit to bitcoin-core/gui that referenced this pull request Nov 2, 2021
…sportDeserializer::GetMessage()

f3e451b [net] Replace GetID() with id in TransportDeserializer constructor (Troy Giorshev)
8c96008 [net] Don't return an optional from TransportDeserializer::GetMessage() (Troy Giorshev)

Pull request description:

  Also, access mapRecvBytesPerMsgCmd with `at()` not `find()`. This
  throws an error if COMMAND_OTHER doesn't exist, which should never
  happen. `find()` instead just accessed the last element, which could make
  debugging more difficult.

  Resolves review comments from PR19107:

  - bitcoin/bitcoin#19107 (comment)
  - bitcoin/bitcoin#19107 (comment)

ACKs for top commit:
  theStack:
    Code-review ACK f3e451b
  ryanofsky:
    Code review ACK f3e451b. Changes since last review in bitcoin/bitcoin#20364 (review) were simplifying by dropping the third commit, rebasing, and cleaning up some style & comments in the first commit.

Tree-SHA512: 37de4b25646116e45eba50206e82ed215b0d9942d4847a172c104da4ed76ea4cee29a6fb119f3c34106a9b384263c576cb8671d452965a468f358d4a3fa3c003
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet