-
Notifications
You must be signed in to change notification settings - Fork 38.7k
net: limit BIP37 filter lifespan (active between 'filterload'..'filterclear') #18544
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
net: limit BIP37 filter lifespan (active between 'filterload'..'filterclear') #18544
Conversation
|
Could add a test for the disconnect? |
82b8976 to
1f3566e
Compare
Indeed, I added a test checking that sending |
…lterclear') Previously, a default match-everything bloom filter was set for every peer, i.e. even before receiving a 'filterload' message and after receiving a 'filterclear' message code branches checking for the existence of the filter by testing the pointer "pfilter" were _always_ executed.
1f3566e to
c4d5ba8
Compare
|
Rebased, after #18533 has been merged. |
maflcko
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK c4d5ba83b2ca5781821cc288295da81156a28277 👍
Show signature and timestamp
Signature:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
ACK c4d5ba83b2ca5781821cc288295da81156a28277 👍
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUjBRAv8DS1SLAG7dVYrnM53l0CpW3L86qsugRb7QX+JR4+fnmqaLkWwg95z80CL
xL4NqnfBkIs3aUzQHtW1Ry0yZA8BuZQf9syg5jVXlFJlSjlJ8l58Obu1VEhPXIhU
pSUNEFAKHGcSZCay6lpuKJ2YESYxf3CWBtObtiC5bA2/NENKt0mMjT3PvH8sbSmA
UvD4qmFdDfU+h/my3hrq8509NP4u2DO029z1i/kw2kRP0BR3ywom4vsBbgyLGsn3
TfUJwA/ZUzHTfcaUJwolkr6fDoS6Xg8b6h6S+FHT5AWDC23D0uK2CSKLoE665P8D
C3CMeVobVgZwwTDUu6ehpm0AJMZ/nuLdtjurO95l8IArronxaY778LZPbqnP14UQ
KC/z1c01wGCzkKqQedA6xI+OaudPBXSAYHtM7OW4O2anlS1OixNX4OHgrYa3lklw
ywUK7s4/7kYp3HasAerziUxx4QFQ1D9c3veimRvkOYtl4MiTSD3I07L+1bat6B6e
4iuKgGpD
=pvkA
-----END PGP SIGNATURE-----
Timestamp of file with hash 94f5012633296cb966cec859d16ca56127a4af35eb21df461ff9a83d033c85d2 -
c4d5ba8 to
7d6cd75
Compare
|
Updated the functional test commit to also check for the |
7d6cd75 to
fb0434a
Compare
b1fff4f to
3c76e61
Compare
|
Updated with @MarcoFalke's suggestion of explicitely waiting for an |
check the following expected behaviors if no filter is set: -> filtered block requests are ignored by the node -> sending a 'filteradd' message is treated as misbehavior (i.e. the peer's banscore increases by 100) also fixes a bug in the on_inv() callback method, which directly modified the type from BLOCK to FILTERED_BLOCK in the received 'inv' message rather than just for the reply Co-authored-by: MarcoFalke <[email protected]>
3c76e61 to
a9ecbdf
Compare
|
Force-pushed again, now also fixes the bug described in #18544 (comment). Updated the commit message to also describe the bugfix and include MarcoFalke as co-author. |
|
re-ACK a9ecbdf, only change is in test code 🕙 Show signature and timestampSignature: Timestamp of file with hash |
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, 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. |
… 'filterload'..'filterclear') a9ecbdf test: add more inactive filter tests to p2p_filter.py (Sebastian Falbesoner) 5eae034 net: limit BIP37 filter lifespan (active between 'filterload' and 'filterclear') (Sebastian Falbesoner) Pull request description: This PR fixes bitcoin#18483. On the master branch, there is currently _always_ a BIP37 filter set for every peer: if not a specific filter is set through a `filterload` message, a default match-everything filter is instanciated and pointed to via the `CBloomFilter` default constructor; that happens both initially, when the containing structure `TxRelay` is constructed: https://github.com/bitcoin/bitcoin/blob/c0b389b33516fb3eaaad7c30bd11dba768882a7e/src/net.h#L812 and after a loaded filter is removed again through a `filterclear` message: https://github.com/bitcoin/bitcoin/blob/c0b389b33516fb3eaaad7c30bd11dba768882a7e/src/net_processing.cpp#L3201 The behaviour was introduced by commit bitcoin@37c6389 (an intentional covert fix for [CVE-2013-5700](bitcoin#18515), according to gmaxwell). This default match-everything filter leads to some unintended side-effects: 1. `getdata` request for filtered blocks (i.e. type `MSG_FILTERED_BLOCK`) are always responded to with `merkleblock`s, even if no filter was set by the peer, see issue bitcoin#18483 (strictly speaking, this is a violation of BIP37) https://github.com/bitcoin/bitcoin/blob/c0b389b33516fb3eaaad7c30bd11dba768882a7e/src/net_processing.cpp#L1504-L1507 2. if a peer sends a `filteradd` message without having loaded a filter via `filterload` before, the intended increasing of the banscore never happens (triggered if `bad` is set to true, a few lines below) https://github.com/bitcoin/bitcoin/blob/c0b389b33516fb3eaaad7c30bd11dba768882a7e/src/net_processing.cpp#L3182-L3186 This PR basically activates the `else`-branch code paths for all checks of `pfilter` again (on the master branch, they are dead code) by limiting the pointer's lifespan: instead of always having a filter set, the `pfilter` is only pointing to a `CBloomFilter`-instance after receiving a `filterload` message and the instance is destroyed again (and the pointer nullified) after receiving a `filterclear` message. Here is a before/after comparison in behaviour: | code part / scenario | master branch | PR branch | | --------------------------------------------- | ---------------------------------- | ---------------------------------------------------- | | `getdata` processing for `MSG_FILTERED_BLOCK` | always responds with `merkleblock` | only responds if filter was set via `filterload` | | `filteradd` processing, no filter was loaded | nothing | peer's banscore increases by 100 (i.e. disconnect) | On the other code parts where `pfilter` is checked there is no change in the logic behaviour (except that `CBloomFilter::IsRelevantAndUpdate()` is unnecessarily called and immediately returned in the master branch). Note that the default constructor of `CBloomFilter` is only used for deserializing the received `filterload` message and nowhere else. The PR also contains a functional test checking that sending `getdata` for filtered blocks is ignored by the node if no bloom filter is set. ACKs for top commit: MarcoFalke: re-ACK a9ecbdf, only change is in test code 🕙 Tree-SHA512: 1a656a6d74ccaf628e7fdca063ba63fbab2089e0b6d0a11be9bbd387c2ee6d3230706ff8ffc1a55711481df3d4547137dd7c9d9184d89eaa43ade4927792d0b6
|
This merge broke the master build on bitcoinbuilds.org. See: https://bitcoinbuilds.org/index.php?ansilog=b3d4f4bf-5d4b-4957-9bf3-91ffe4a799fb.log#l2935 |
c743718 test: add further BIP37 size limit checks to p2p_filter.py (Sebastian Falbesoner) Pull request description: This is a follow-up PR to #18628. In addition to the hash-functions limit test introduced with commit fa4c29b, it adds checks for the following size limits as defined in [BIP37](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki): ad message type `filterload`: > The filter itself is simply a bit field of arbitrary byte-aligned size. The maximum size is **36,000 bytes**. ad message type `filteradd`: > The data field must be smaller than or equal to **520 bytes** in size (the maximum size of any potentially matched object). Also introduces new constants for the limits (or reuses the max script size constant in case for the `filteradd` limit). Also fixes #18711 by changing the misbehaviour check on "filteradd without filterset" (introduced with #18544) below to also use the more commonly used `assert_debug_log` method. ACKs for top commit: MarcoFalke: ACK c743718 robot-visions: ACK c743718 jonasschnelli: utACK c743718. Seems to fix it: https://bitcoinbuilds.org/index.php?build=2524 Tree-SHA512: a03e7639263eb36a381922afb4e1d0ed2ae286f2ad2e7bbd922509a043ddf6cfd08747e01d54d29bfb8f54b66908f653974b9c347e4ca4f43332b586778893be
|
Yes, it was a silent merge conflict on the test script. Should be fixed now. |
See #18721 |
…_filter.py c743718 test: add further BIP37 size limit checks to p2p_filter.py (Sebastian Falbesoner) Pull request description: This is a follow-up PR to bitcoin#18628. In addition to the hash-functions limit test introduced with commit bitcoin@fa4c29b, it adds checks for the following size limits as defined in [BIP37](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki): ad message type `filterload`: > The filter itself is simply a bit field of arbitrary byte-aligned size. The maximum size is **36,000 bytes**. ad message type `filteradd`: > The data field must be smaller than or equal to **520 bytes** in size (the maximum size of any potentially matched object). Also introduces new constants for the limits (or reuses the max script size constant in case for the `filteradd` limit). Also fixes bitcoin#18711 by changing the misbehaviour check on "filteradd without filterset" (introduced with bitcoin#18544) below to also use the more commonly used `assert_debug_log` method. ACKs for top commit: MarcoFalke: ACK c743718 robot-visions: ACK c743718 jonasschnelli: utACK c743718. Seems to fix it: https://bitcoinbuilds.org/index.php?build=2524 Tree-SHA512: a03e7639263eb36a381922afb4e1d0ed2ae286f2ad2e7bbd922509a043ddf6cfd08747e01d54d29bfb8f54b66908f653974b9c347e4ca4f43332b586778893be
…rclear') Summary: > net: limit BIP37 filter lifespan (active between 'filterload' and 'filterclear') > Previously, a default match-everything bloom filter was set for every peer, > i.e. even before receiving a 'filterload' message and after receiving a > 'filterclear' message code branches checking for the existence of the filter > by testing the pointer "pfilter" were _always_ executed. > test: add more inactive filter tests to p2p_filter.py > check the following expected behaviors if no filter is set: > -> filtered block requests are ignored by the node > -> sending a 'filteradd' message is treated as misbehavior > > also fixes a bug in the on_inv() callback method, which > directly modified the type from BLOCK to FILTERED_BLOCK > in the received 'inv' message rather than just for the reply > > Co-authored-by: MarcoFalke <[email protected]> This is a backport of Core [[bitcoin/bitcoin#18544 | PR18544]] I had to change the last test to use a different way to detect misbehavior, because banscore was deprecated in D8798 (this would have been applied in [[bitcoin/bitcoin#18672 | PR18672]], if the backports had been done in sequential order) Test Plan: `ninja all check-all` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Differential Revision: https://reviews.bitcoinabc.org/D8949
…n (active between 'filterload'..'filterclear') (#4043) * partial backport 18544: net: limit BIP37 filter lifespan (active between 'filterload'..'filterclear') Previously, a default match-everything bloom filter was set for every peer, i.e. even before receiving a 'filterload' message and after receiving a 'filterclear' message code branches checking for the existence of the filter by testing the pointer "pfilter" were _always_ executed. * net: Match the backport PR a bit more Co-authored-by: xdustinface <[email protected]>
This PR fixes #18483. On the master branch, there is currently always a BIP37 filter set for every peer: if not a specific filter is set through a
filterloadmessage, a default match-everything filter is instanciated and pointed to via theCBloomFilterdefault constructor; that happens both initially, when the containing structureTxRelayis constructed:bitcoin/src/net.h
Line 812 in c0b389b
and after a loaded filter is removed again through a
filterclearmessage:bitcoin/src/net_processing.cpp
Line 3201 in c0b389b
The behaviour was introduced by commit 37c6389 (an intentional covert fix for CVE-2013-5700, according to gmaxwell).
This default match-everything filter leads to some unintended side-effects:
getdatarequest for filtered blocks (i.e. typeMSG_FILTERED_BLOCK) are always responded to withmerkleblocks, even if no filter was set by the peer, see issue BIP37: 'getdata' request for filtered blocks is answered with 'merkleblock's even if no filter is set #18483 (strictly speaking, this is a violation of BIP37)bitcoin/src/net_processing.cpp
Lines 1504 to 1507 in c0b389b
filteraddmessage without having loaded a filter viafilterloadbefore, the intended increasing of the banscore never happens (triggered ifbadis set to true, a few lines below)bitcoin/src/net_processing.cpp
Lines 3182 to 3186 in c0b389b
This PR basically activates the
else-branch code paths for all checks ofpfilteragain (on the master branch, they are dead code) by limiting the pointer's lifespan: instead of always having a filter set, thepfilteris only pointing to aCBloomFilter-instance after receiving afilterloadmessage and the instance is destroyed again (and the pointer nullified) after receiving afilterclearmessage.Here is a before/after comparison in behaviour:
getdataprocessing forMSG_FILTERED_BLOCKmerkleblockfilterloadfilteraddprocessing, no filter was loadedOn the other code parts where
pfilteris checked there is no change in the logic behaviour (except thatCBloomFilter::IsRelevantAndUpdate()is unnecessarily called and immediately returned in the master branch).Note that the default constructor of
CBloomFilteris only used for deserializing the receivedfilterloadmessage and nowhere else. The PR also contains a functional test checking that sendinggetdatafor filtered blocks is ignored by the node if no bloom filter is set.