Skip to content

Commit e175a20

Browse files
committed
Merge bitcoin/bitcoin#21644: p2p, bugfix: use NetPermissions::HasFlag() in CConnman::Bind()
36fb036 p2p: allow NetPermissions::ClearFlag() only with PF_ISIMPLICIT (Jon Atack) 4e0d578 test: add net permissions noban/download unit test coverage (Jon Atack) dde69f2 p2p, bugfix: use NetPermissions::HasFlag() in CConnman::Bind() (Jon Atack) Pull request description: This is a bugfix follow-up to #16248 and #19191 that was noticed in #21506. Both v0.21 and master are affected. Since #19191, noban is a multi-flag that implies download, so the conditional in `CConnman::Bind()` using a bitwise AND on noban will return the same result for both the noban status and the download status. This means that download peers are incorrectly not being added to local addresses because they are mistakenly seen as noban peers. The second commit adds unit test coverage to illustrate and test the noban/download relationship and the `NetPermissions` operations involving them. The final commit adds documentation and disallows calling `NetPermissions::ClearFlag()` with any second param other than `NetPermissionFlags` "implicit" -- per current usage in the codebase -- because `ClearFlag()` should not be called with any second param that is a subflag of a multiflag, e.g. "relay" or "download," as that would leave the result in an invalid state corresponding to none of the existing NetPermissionFlags. Thanks to Vasil Dimov for noticing this. ACKs for top commit: theStack: re-ACK 36fb036 ☕ vasild: ACK 36fb036 hebasto: ACK 36fb036, I have reviewed the code and it looks OK, I agree it can be merged. kallewoof: Code review ACK 36fb036 Tree-SHA512: 5fbc7ddbf31d06b35bf238f4d77ef311e6b6ef2e1bb9893f32f889c1a0f65774a3710dcb21d94317fe6166df9334a9f2d42630809e7fe8cbd797dd6f6fc49491
2 parents 94f8353 + 36fb036 commit e175a20

File tree

4 files changed

+36
-5
lines changed

4 files changed

+36
-5
lines changed

src/net.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,8 +2399,9 @@ NodeId CConnman::GetNewNodeId()
23992399

24002400

24012401
bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions) {
2402-
if (!(flags & BF_EXPLICIT) && !IsReachable(addr))
2402+
if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) {
24032403
return false;
2404+
}
24042405
bilingual_str strError;
24052406
if (!BindListenPort(addr, strError, permissions)) {
24062407
if ((flags & BF_REPORT_ERROR) && clientInterface) {
@@ -2409,7 +2410,7 @@ bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags
24092410
return false;
24102411
}
24112412

2412-
if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !(permissions & PF_NOBAN)) {
2413+
if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !NetPermissions::HasFlag(permissions, NetPermissionFlags::PF_NOBAN)) {
24132414
AddLocal(addr, LOCAL_BIND);
24142415
}
24152416

src/net_permissions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,14 @@ class NetPermissions
5151
{
5252
flags = static_cast<NetPermissionFlags>(flags | f);
5353
}
54+
//! ClearFlag is only called with `f` == NetPermissionFlags::PF_ISIMPLICIT.
55+
//! If that should change in the future, be aware that ClearFlag should not
56+
//! be called with a subflag of a multiflag, e.g. NetPermissionFlags::PF_RELAY
57+
//! or NetPermissionFlags::PF_DOWNLOAD, as that would leave `flags` in an
58+
//! invalid state corresponding to none of the existing flags.
5459
static inline void ClearFlag(NetPermissionFlags& flags, NetPermissionFlags f)
5560
{
61+
assert(f == NetPermissionFlags::PF_ISIMPLICIT);
5662
flags = static_cast<NetPermissionFlags>(flags & ~f);
5763
}
5864
};

src/test/fuzz/net_permissions.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ FUZZ_TARGET(net_permissions)
2525
(void)NetPermissions::ToStrings(net_whitebind_permissions.m_flags);
2626
(void)NetPermissions::AddFlag(net_whitebind_permissions.m_flags, net_permission_flags);
2727
assert(NetPermissions::HasFlag(net_whitebind_permissions.m_flags, net_permission_flags));
28-
(void)NetPermissions::ClearFlag(net_whitebind_permissions.m_flags, net_permission_flags);
28+
(void)NetPermissions::ClearFlag(net_whitebind_permissions.m_flags, NetPermissionFlags::PF_ISIMPLICIT);
2929
(void)NetPermissions::ToStrings(net_whitebind_permissions.m_flags);
3030
}
3131

@@ -35,7 +35,7 @@ FUZZ_TARGET(net_permissions)
3535
(void)NetPermissions::ToStrings(net_whitelist_permissions.m_flags);
3636
(void)NetPermissions::AddFlag(net_whitelist_permissions.m_flags, net_permission_flags);
3737
assert(NetPermissions::HasFlag(net_whitelist_permissions.m_flags, net_permission_flags));
38-
(void)NetPermissions::ClearFlag(net_whitelist_permissions.m_flags, net_permission_flags);
38+
(void)NetPermissions::ClearFlag(net_whitelist_permissions.m_flags, NetPermissionFlags::PF_ISIMPLICIT);
3939
(void)NetPermissions::ToStrings(net_whitelist_permissions.m_flags);
4040
}
4141
}

src/test/netbase_tests.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,28 @@ BOOST_AUTO_TEST_CASE(netpermissions_test)
395395
BOOST_CHECK(NetWhitebindPermissions::TryParse("@1.2.3.4:32", whitebindPermissions, error));
396396
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_NONE);
397397

398+
NetWhitebindPermissions noban, noban_download, download_noban, download;
399+
400+
// "noban" implies "download"
401+
BOOST_REQUIRE(NetWhitebindPermissions::TryParse("[email protected]:32", noban, error));
402+
BOOST_CHECK_EQUAL(noban.m_flags, NetPermissionFlags::PF_NOBAN);
403+
BOOST_CHECK(NetPermissions::HasFlag(noban.m_flags, NetPermissionFlags::PF_DOWNLOAD));
404+
BOOST_CHECK(NetPermissions::HasFlag(noban.m_flags, NetPermissionFlags::PF_NOBAN));
405+
406+
// "noban,download" is equivalent to "noban"
407+
BOOST_REQUIRE(NetWhitebindPermissions::TryParse("noban,[email protected]:32", noban_download, error));
408+
BOOST_CHECK_EQUAL(noban_download.m_flags, noban.m_flags);
409+
410+
// "download,noban" is equivalent to "noban"
411+
BOOST_REQUIRE(NetWhitebindPermissions::TryParse("download,[email protected]:32", download_noban, error));
412+
BOOST_CHECK_EQUAL(download_noban.m_flags, noban.m_flags);
413+
414+
// "download" excludes (does not imply) "noban"
415+
BOOST_REQUIRE(NetWhitebindPermissions::TryParse("[email protected]:32", download, error));
416+
BOOST_CHECK_EQUAL(download.m_flags, NetPermissionFlags::PF_DOWNLOAD);
417+
BOOST_CHECK(NetPermissions::HasFlag(download.m_flags, NetPermissionFlags::PF_DOWNLOAD));
418+
BOOST_CHECK(!NetPermissions::HasFlag(download.m_flags, NetPermissionFlags::PF_NOBAN));
419+
398420
// Happy path, can parse flags
399421
BOOST_CHECK(NetWhitebindPermissions::TryParse("bloom,[email protected]:32", whitebindPermissions, error));
400422
// forcerelay should also activate the relay permission
@@ -407,7 +429,7 @@ BOOST_AUTO_TEST_CASE(netpermissions_test)
407429

408430
// Allow dups
409431
BOOST_CHECK(NetWhitebindPermissions::TryParse("bloom,relay,noban,[email protected]:32", whitebindPermissions, error));
410-
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_BLOOMFILTER | PF_RELAY | PF_NOBAN);
432+
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_BLOOMFILTER | PF_RELAY | PF_NOBAN | PF_DOWNLOAD); // "noban" implies "download"
411433

412434
// Allow empty
413435
BOOST_CHECK(NetWhitebindPermissions::TryParse("bloom,relay,,[email protected]:32", whitebindPermissions, error));
@@ -428,6 +450,8 @@ BOOST_AUTO_TEST_CASE(netpermissions_test)
428450
// Happy path for whitelist parsing
429451
BOOST_CHECK(NetWhitelistPermissions::TryParse("[email protected]", whitelistPermissions, error));
430452
BOOST_CHECK_EQUAL(whitelistPermissions.m_flags, PF_NOBAN);
453+
BOOST_CHECK(NetPermissions::HasFlag(whitelistPermissions.m_flags, NetPermissionFlags::PF_NOBAN));
454+
431455
BOOST_CHECK(NetWhitelistPermissions::TryParse("bloom,forcerelay,noban,[email protected]/32", whitelistPermissions, error));
432456
BOOST_CHECK_EQUAL(whitelistPermissions.m_flags, PF_BLOOMFILTER | PF_FORCERELAY | PF_NOBAN | PF_RELAY);
433457
BOOST_CHECK(error.empty());

0 commit comments

Comments
 (0)