signet: Fix uninitialized read in validation #20035

pull MarcoFalke wants to merge 3 commits into bitcoin:master from MarcoFalke:2009-signetUninitRead changing 2 files +9 −11
  1. MarcoFalke commented at 12:37 pm on September 29, 2020: member
  2. MarcoFalke commented at 12:41 pm on September 29, 2020: member

    Too sad that teaching the compiler to warn about this would make the code massively verbose, but maybe it is worth a shot now that this is the second time this year?

  3. theStack commented at 12:54 pm on September 29, 2020: member

    Concept ACK

    The parameters BIP16Exception and BIP34Hash are also not initialized for Signet?

  4. MarcoFalke commented at 1:01 pm on September 29, 2020: member
    unit256 are default initialized to all-zeros
  5. theStack commented at 1:24 pm on September 29, 2020: member

    unit256 are default initialized to all-zeros

    Right, in those case there is no uninitialized read.

    Still, looking at mainnet, testnet and regtest, without exception all parameters (i.e. all 22 fields of struct Params) are explicitely initialized – hence I think for signet and all future *nets the same should be done. Both for consistency and do avoid such uninitialized read errors in the feature. The following params are not set for signet, i.e. uninitialized or default initialized:

    • MinBIP9WarningHeight (fixed in this PR)
    • nMinimumChainWork
    • defaultAssumeValid
    • BIP16Exception
    • BIP34Hash
  6. DrahtBot added the label Validation on Sep 29, 2020
  7. practicalswift commented at 7:47 pm on September 29, 2020: contributor

    @MarcoFalke Nice catch! How did you find this one?

    It’s always a bit sad to see unitialized reads enter our code base without being caught automatically at CI stage by either dynamic analysis (MSAN or Valgrind) or static analysis :(

  8. practicalswift commented at 4:32 am on September 30, 2020: contributor

    The UUM takes place in WarningBitsConditionChecker::Condition which is executed in the message handler thread:

     0$ valgrind --exit-on-first-error=yes --track-origins=yes --suppressions=contrib/valgrind.supp src/bitcoind -signet
     1
     2==9443== Thread 23 b-msghand:
     3==9443== Conditional jump or move depends on uninitialised value(s)
     4==9443==    at 0x6F3E65: WarningBitsConditionChecker::Condition(CBlockIndex const*, Consensus::Params const&) const (validation.cpp:1862)
     5==9443==    by 0x744269: AbstractThresholdConditionChecker::GetStateFor(CBlockIndex const*, Consensus::Params const&, std::map<CBlockIndex const*, ThresholdState, std::less<CBlockIndex const*>, std::allocator<std::pair<CBlockIndex const* const, ThresholdState> > >&) const (versionbits.cpp:70)
     6==9443==    by 0x6D77FA: UpdateTip(CTxMemPool&, CBlockIndex const*, CChainParams const&) (validation.cpp:2458)
     7==9443==    by 0x6D8B64: CChainState::ConnectTip(BlockValidationState&, CChainParams const&, CBlockIndex*, std::shared_ptr<CBlock const> const&, ConnectTrace&, DisconnectedBlockTransactions&) (validation.cpp:2649)
     8==9443==    by 0x6D9712: CChainState::ActivateBestChainStep(BlockValidationState&, CChainParams const&, CBlockIndex*, std::shared_ptr<CBlock const> const&, bool&, ConnectTrace&) (validation.cpp:2781)
     9==9443==    by 0x6D9E8F: CChainState::ActivateBestChain(BlockValidationState&, CChainParams const&, std::shared_ptr<CBlock const>) (validation.cpp:2908)
    10==9443==    by 0x6E089E: ChainstateManager::ProcessNewBlock(CChainParams const&, std::shared_ptr<CBlock const>, bool, bool*) (validation.cpp:3864)
    11==9443==    by 0x3FADD3: PeerManager::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, CDataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l> >, std::atomic<bool> const&) (net_processing.cpp:3506)
    12==9443==    by 0x3FDA75: PeerManager::ProcessMessages(CNode*, std::atomic<bool>&) (net_processing.cpp:3864)
    13==9443==    by 0x390065: CConnman::ThreadMessageHandler() (net.cpp:2155)
    14==9443==    by 0x3E018D: void std::__invoke_impl<void, void (CConnman::*&)(), CConnman*&>(std::__invoke_memfun_deref, void (CConnman::*&)(), CConnman*&) (invoke.h:73)
    15==9443==    by 0x3DB61C: std::__invoke_result<void (CConnman::*&)(), CConnman*&>::type std::__invoke<void (CConnman::*&)(), CConnman*&>(void (CConnman::*&)(), CConnman*&) (invoke.h:95)
    16==9443==  Uninitialised value was created by a heap allocation
    17==9443==    at 0x4C3052A: operator new(unsigned long) (vg_replace_malloc.c:342)
    18==9443==    by 0xA1C134: CreateChainParams(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (chainparams.cpp:495)
    19==9443==    by 0xA1C31B: SelectParams(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (chainparams.cpp:505)
    20==9443==    by 0x30ABB6: AppInit(int, char**) (bitcoind.cpp:82)
    21==9443==    by 0x30B53E: main (bitcoind.cpp:172)
    
  9. practicalswift commented at 4:39 am on September 30, 2020: contributor

    Unfortunately it seems like this UUM is not triggered by the code paths exercised by feature_signet.py. Covering the triggering code path in the functional test would be nice as part of this fix :)

    0$ test/functional/test_runner.py --valgrind --timeout-factor=0 feature_signet
    1
    2TEST              | STATUS    | DURATION
    3
    4feature_signet.py | ✓ Passed  | 151 s
    5
    6ALL               | ✓ Passed  | 151 s (accumulated) 
    7Runtime: 151 s
    
  10. kallewoof approved
  11. kallewoof commented at 7:05 am on September 30, 2020: member
    utACK
  12. MarcoFalke force-pushed on Sep 30, 2020
  13. MarcoFalke commented at 12:53 pm on September 30, 2020: member
    Pushed some non-bugfix changes
  14. DrahtBot commented at 7:24 pm on September 30, 2020: member

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

    Conflicts

    No conflicts as of last run.

  15. kallewoof commented at 4:43 am on October 1, 2020: member
    re-ACK. Agree with moving chain work / assume valid comments.
  16. practicalswift commented at 6:37 am on October 1, 2020: contributor
    @kallewoof @MarcoFalke Have someone investigated why this UUM appear not to be exercised in the functional tests?
  17. kallewoof commented at 7:03 am on October 1, 2020: member

    @practicalswift @MarcoFalke I made a minimal test that fails on master: https://github.com/kallewoof/bitcoin/tree/202010-signet-uuv-min9-test

    0test/validation_block_tests.cpp:379: error: in "validation_block_tests/chainparameters": check chain->GetConsensus().MinBIP9WarningHeight == 0 has failed [809056355 != 0]
    12020-10-01T06:51:08.729020Z [scheduler] scheduler thread exit
    2test/validation_block_tests.cpp:376: Leaving test case "chainparameters"; testing time: 79044us
    3test/validation_block_tests.cpp:33: Leaving test suite "validation_block_tests"; testing time: 13338900us
    4test/validation_chainstate_tests.cpp:16: Test suite "validation_chainstate_tests" is skipped because disabled
    5[...]
    6wallet/test/scriptpubkeyman_tests.cpp:13: Test suite "scriptpubkeyman_tests" is skipped because disabled
    7Leaving test module "Bitcoin Core Test Suite"; testing time: 13340245us
    8
    9*** 1 failure is detected in the test module "Bitcoin Core Test Suite"
    

    The test succeeds on top of this PR.

  18. MarcoFalke commented at 7:08 am on October 1, 2020: member
    The versionbits condition isn’t evaluated for the first retarget period after the genesis block, so no test hits it.
  19. theStack approved
  20. theStack commented at 7:11 am on October 1, 2020: member
    ACK fa82143e41c067e7d16d612c775701be94974d54 🩹
  21. jonatack commented at 8:22 am on October 1, 2020: member

    fa82143e maybe also change

    0--- a/src/chainparams.cpp
    1+++ b/src/chainparams.cpp
    2@@ -365,7 +365,7 @@ public:
    3         consensus.nSubsidyHalvingInterval = 150;
    4         consensus.BIP16Exception = uint256();
    5         consensus.BIP34Height = 500; // BIP34 activated on regtest (Used in functional tests)
    6-        consensus.BIP34Hash = uint256();
    7+        consensus.BIP34Hash = uint256{};
    
  22. in src/chainparams.cpp:327 in fa82143e41 outdated
    314@@ -317,6 +315,7 @@ class SigNetParams : public CChainParams {
    315         consensus.fPowNoRetargeting = false;
    316         consensus.nRuleChangeActivationThreshold = 1916;
    317         consensus.nMinerConfirmationWindow = 2016;
    318+        consensus.MinBIP9WarningHeight = 0;
    


    jonatack commented at 8:27 am on October 1, 2020:

    fadb384e perhaps group MinBIP9WarningHeight with the other height settings as done in the other three chains

     0--- a/src/chainparams.cpp
     1+++ b/src/chainparams.cpp
     2@@ -309,13 +309,13 @@ public:
     3        consensus.BIP66Height = 1;
     4        consensus.CSVHeight = 1;
     5        consensus.SegwitHeight = 1;
     6+        consensus.MinBIP9WarningHeight = 0;
     7        consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
     8        consensus.nPowTargetSpacing = 10 * 60;
     9        consensus.fPowAllowMinDifficultyBlocks = false;
    10        consensus.fPowNoRetargeting = false;
    11        consensus.nRuleChangeActivationThreshold = 1916;
    12        consensus.nMinerConfirmationWindow = 2016;
    13-        consensus.MinBIP9WarningHeight = 0;
    

    MarcoFalke commented at 8:32 am on October 1, 2020:
    I’ve put it in the line right before powLimit, like in all other chain constructors
  23. jonatack commented at 8:27 am on October 1, 2020: member
    Great find – LGTM modulo the two comments
  24. in src/chainparams.cpp:398 in fa82143e41 outdated
    381@@ -378,8 +382,8 @@ class CRegTestParams : public CChainParams {
    382         consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0;
    383         consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
    384 
    385-        consensus.nMinimumChainWork = uint256S("0x00");
    


    promag commented at 8:43 am on October 1, 2020:

    fa82143e41c067e7d16d612c775701be94974d54

    Not sure what is the motivation of being explicit here, I’d just remove these cases.


    MarcoFalke commented at 8:58 am on October 1, 2020:
  25. promag commented at 8:44 am on October 1, 2020: member
    Code review ACK fa82143e41c067e7d16d612c775701be94974d54.
  26. jonatack commented at 11:28 am on October 1, 2020: member
    Code review ACK fa82143e41c067e7d16d612c775701be94974d54
  27. practicalswift commented at 4:22 pm on October 1, 2020: contributor

    @MarcoFalke

    Want to share how you found this one (great find!)? :) Was it found by static analysis or dynamic analysis? Automatic testing or manual testing?

    I’m thinking about what we can learn from this UUM case. More specifically I’m thinking about potential ways to improve manual and/or automated processes to catch UUM:s pre-merge (in the spirit of #18288, #17633, #18159, #18166 and similar attempts to kill this bug class for good) :)


    FWIW, some previous UUM cases if someone wants to analyse specific instances of this bug class more in-depth:

  28. MarcoFalke commented at 4:26 pm on October 1, 2020: member
    It was found by reading/reviewing the code
  29. michaelfolkson commented at 12:52 pm on October 6, 2020: contributor

    Concept ACK, Approach ACK

    Haven’t looked into @kallewoof test but presumably that will be in a follow up PR.

    Thanks for sharing resources too @practicalswift. Added to a StackExchange post.

  30. practicalswift commented at 6:29 pm on October 6, 2020: contributor
    ACK fa82143e41c067e7d16d612c775701be94974d54: diff looks correct
  31. MarcoFalke added this to the milestone 0.21.0 on Oct 9, 2020
  32. laanwj commented at 8:57 am on October 15, 2020: member
    Sorry, needs rebase (probably with taproot changes)
  33. signet: Fix uninitialized read in validation fa64892b82
  34. doc: Move assumed-values doxygen comments to header fa729cdb2c
  35. MarcoFalke force-pushed on Oct 15, 2020
  36. MarcoFalke commented at 9:30 am on October 15, 2020: member
    Rebased
  37. kallewoof commented at 3:43 am on October 16, 2020: member
    Typo in 3rd commit message (unit256).
  38. Initialize default-initialized uint256 consensus params to zero explicitly fa723e3d43
  39. MarcoFalke force-pushed on Oct 16, 2020
  40. MarcoFalke commented at 4:32 am on October 16, 2020: member
    Fixed typo in commit msg
  41. practicalswift commented at 6:07 am on October 16, 2020: contributor
    re-ACK fa723e3d43e63e8424d97d21d8f2cc8136aba206: patch still looks correct
  42. kallewoof commented at 6:47 am on October 16, 2020: member
    ReACK fa723e3d43e63e8424d97d21d8f2cc8136aba206
  43. theStack approved
  44. theStack commented at 8:15 am on October 16, 2020: member
    re-ACK fa723e3d43e63e8424d97d21d8f2cc8136aba206 🍐
  45. laanwj merged this on Oct 16, 2020
  46. laanwj closed this on Oct 16, 2020

  47. MarcoFalke deleted the branch on Oct 16, 2020
  48. sidhujag referenced this in commit 0b2a28fa79 on Oct 16, 2020
  49. DrahtBot locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-22 00:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me