Skip to content

Conversation

laanwj
Copy link
Member

@laanwj laanwj commented Nov 20, 2020

Instead of the ever-messier text parsing of the output of the readelf tool (which is clearly meant for human consumption not to be machine parseable), parse the ELF binaries directly.

Add a small dependency-less ELF parser specific to the checks.

This is slightly more secure, too, because it removes potential ambiguity due to misparsing and changes in the output format of elfread. It also allows for stricter and more specific ELF format checks in the future.

This removes the build-time dependency for readelf.

It passes the test-security-check for me locally, though I haven't checked on all platforms. I've checked that this works on the cross-compile output for all ELF platforms supported by Bitcoin Core at the moment, as well as PPC64 LE and BE.

@fanquake
Copy link
Member

Concept ACK 🧚

@laanwj laanwj force-pushed the 2020_11_pixie branch 3 times, most recently from 18a1c5a to 8c3b297 Compare November 20, 2020 13:14
@jonatack
Copy link
Member

Concept ACK

@laanwj
Copy link
Member Author

laanwj commented Nov 20, 2020

I've ported the changes for PPC64 from #14066 in an extra commit.

@DrahtBot
Copy link
Contributor

DrahtBot commented Nov 20, 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.

@laanwj
Copy link
Member Author

laanwj commented Nov 21, 2020

Added mypy annotations. This found a few (small) actual bugs, and might make review easier by clarifying expected types.

laanwj and others added 2 commits November 22, 2020 11:11
Instead of the ever-messier text parsing of the output of the readelf
tool (which is clearly meant for human consumption not to be machine
parseable), parse the ELF binaries directly.

Add a small dependency-less ELF parser specific to the checks.

This is slightly more secure, too, because it removes potential
ambiguity due to misparsing and changes in the output format of `elfread`. It
also allows for stricter and more specific ELF format checks in the future.

This removes the build-time dependency for `readelf`.

It passes the test-security-check for me locally, though I haven't
checked on all platforms.
@theStack
Copy link
Contributor

Concept ACK

@sipa
Copy link
Member

sipa commented Nov 23, 2020

Concept ACK.

ELF looks remarkably simple!

@laanwj
Copy link
Member Author

laanwj commented Nov 23, 2020

ELF looks remarkably simple!

The secret is not needing to resolve relocations 🙂 That is where most of the verbose platform specific trickery comes in.

Edit: not only don't we have any security checks that involve relocations and relocated code, so it's unnecessary to parse them, all the bitcoin binaries are compiled as position independent code so there shouldn't be that many at all. I still see some relocations for dynamic linking machinery like .plt and .got sections.

@practicalswift
Copy link
Contributor

Concept ACK: removing dependencies improves robustness

@laanwj
Copy link
Member Author

laanwj commented Nov 23, 2020

It's not really the dependency that is the problem here. Sure, needing to call out to an utility less is nice, but readelf is part of binutils that we require for build. If it had a stable, predictable output format for machine parsing (like git's plumbing/porcelain distinction), this wouldn't be needed. The problem is basing security checks on an ambiguous human-friendly output format.

@luke-jr
Copy link
Member

luke-jr commented Nov 25, 2020

Concept ACK

@laanwj
Copy link
Member Author

laanwj commented Nov 26, 2020

Would be nice to get #20476 in first, which adds a test that the symbol check can actually fail.

@DrahtBot
Copy link
Contributor

Guix builds

File commit afdfd3c
(master)
commit 2cc7952
(master and this pull)
*-aarch64-linux-gnu-debug.tar.gz 321e361023e8ea7b... 813144f84559e0dc...
*-aarch64-linux-gnu.tar.gz b054d1129516836e... 184917064f174e78...
*-arm-linux-gnueabihf-debug.tar.gz cdd6185a356e7a80... 883c572d0fe1a7db...
*-arm-linux-gnueabihf.tar.gz 4db9b1126b6601b7... 8f212d72c0159656...
*-riscv64-linux-gnu-debug.tar.gz df4a6eb0267f7140... 12e5d6bdec38909f...
*-riscv64-linux-gnu.tar.gz 3ff6d83bd5983e2b... e252e5ded636a464...
*-win-unsigned.tar.gz 0dbc83ed5f22a4db... 68b64bab11c74876...
*-win64-debug.zip 539b210aa13b56bc... 9f1868590f5c2034...
*-win64-setup-unsigned.exe 5ff779deff3db721... c3d72b942f3ed28a...
*-win64.zip 4e50c84031e8b116... c78d5b2dce8fab09...
*-x86_64-linux-gnu-debug.tar.gz 345daa571d3557b0... 32a8cd9a90d81191...
*-x86_64-linux-gnu.tar.gz 60655c6fb26e8633... 8a90973bb90f451b...
*.tar.gz 0ddcf17cb856ed92... d150e18f32cf35ab...
guix_build.log 6670400b0a6511d0... 1b9c8c06b0d5ed02...
guix_build.log.diff 70d1bc211652bbf4...

@DrahtBot
Copy link
Contributor

DrahtBot commented Dec 1, 2020

Gitian builds

File commit e2ff5e7
(master)
commit 1c4188e
(master and this pull)
bitcoin-core-linux-22-res.yml 44e52af36236879f... ed4680968e93faa5...
bitcoin-core-osx-22-res.yml 71d5fb0e6642d6b0... 127fc6fd6c335c03...
bitcoin-core-win-22-res.yml 0148a2f5e7295184... a56ae5d4153d1349...
*-aarch64-linux-gnu-debug.tar.gz 383e84aaa96f342a... 26fbc2d21bada83d...
*-aarch64-linux-gnu.tar.gz 3558211891c0484a... a35fd2ae3605c54f...
*-arm-linux-gnueabihf-debug.tar.gz 5ebbb475a590480a... 52568603abb0f82d...
*-arm-linux-gnueabihf.tar.gz 60951d893e2688b6... b7c3b23abd9e83d9...
*-osx-unsigned.dmg 7cba6edda598c96c... 56e862ccf0d2b4eb...
*-osx64.tar.gz ea2ab5c893780a2e... ba06f4bfd21a3d07...
*-riscv64-linux-gnu-debug.tar.gz 0c20a43923efcd5f... 500c8c3ec67bcaad...
*-riscv64-linux-gnu.tar.gz 8d3632d81c77eff1... ba164e9b54dbb098...
*-win64-debug.zip 72c35e133cf9a0db... c0afdc8cd087028a...
*-win64-setup-unsigned.exe 55c17bfff54273e5... 3716ec12171f7369...
*-win64.zip f7bf6737c7f741c3... 19e38e38b95c53b1...
*-x86_64-linux-gnu-debug.tar.gz abf91baef5c44686... 03794e9328c8b547...
*-x86_64-linux-gnu.tar.gz 75fda490174df335... ab84f605ba4d0716...
*.tar.gz 793a2c7af39452d5... e07ea56a79dd81a3...
linux-build.log 9c5461a914e1f4c0... 1fbb119f2f0ef4ac...
osx-build.log 5adaf67afbaf00fc... 85dd7dace784a1a6...
win-build.log 756101ecccffabf0... 062b62cf4af16bc9...
bitcoin-core-linux-22-res.yml.diff 2edae2388d844498...
bitcoin-core-osx-22-res.yml.diff f0b350f311f376f3...
bitcoin-core-win-22-res.yml.diff cb6211ee06a2ddc9...
linux-build.log.diff 7b880e3e3f0990cf...
osx-build.log.diff 291601d4a5cea40e...
win-build.log.diff e7b782648941c2c2...

@laanwj
Copy link
Member Author

laanwj commented Dec 3, 2020

Good to see that both guix and gitian builds (well, the checks) passed for all platforms.

@laanwj
Copy link
Member Author

laanwj commented Dec 7, 2020

Closing and reopening to re-trigger Travis with #20476 in.

@laanwj laanwj closed this Dec 7, 2020
@laanwj laanwj reopened this Dec 7, 2020
@maflcko
Copy link
Member

maflcko commented Dec 7, 2020

cirrus won't re-trigger on open-close, but on a push only (e.g. rebase or other any other git push)

@laanwj
Copy link
Member Author

laanwj commented Dec 7, 2020

sigh okay, added an empty commit to re-trgger CI, please remind me to remove it before merge.
Edit: it passed, empty commit removed again.

@fanquake
Copy link
Member

Just wanted to note that this will fail the RELRO check if run against binaries older than 0.17.x, because they have the deprecated DT_BIND_NOW array tag:

/usr/local/opt/binutils/bin/readelf -dw ~/Downloads/bitcoin-0.16.3/bin/bitcoind | rg -i bind
...
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x0000000000000018 (BIND_NOW)           
 0x000000006ffffffb (FLAGS_1)            Flags: NOW

rather than the DF_BIND_NOW flag:

/usr/local/opt/binutils/bin/readelf -dw ~/Downloads/bitcoin-0.17.2/bin/bitcoind | rg -i bind
...
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW PIE

and our current script checks for either. Not that it's a blocker, just noticed while testing.

@laanwj
Copy link
Member Author

laanwj commented Dec 14, 2020

Thanks for testing!

In contrast to passing, failing is safe in this case. I think it's fine to support the 'new way' only, as this is what we want our binaries to use.

Edit: or should we check for both to be present because old platforms might ignore the new flag? No, because new toolchains don't set the old flag.

@sipa
Copy link
Member

sipa commented Dec 15, 2020

Concept & approach ACK. I have tried the pixie module on a few binaries and seems to give reasonable results, but haven't reviewed the code in detail or verified against any ELF format reference.

@laanwj
Copy link
Member Author

laanwj commented Dec 17, 2020

@sipa Thanks for testing and looking at it!

FWIW, verifying it against elf.h is probably easier than verifying it against the ELF spec as it follows a similar structure. But I hope the security and symbol-check tests are enough to give confidence that this has the same functionality as the elfread based implementation.
(apart from the deprecated DT_BIND_NOW check)

@laanwj
Copy link
Member Author

laanwj commented Dec 18, 2020

I'm going to merge this so that #14066 can be rebased on top and we can introduce the POWER architecture binaries in the beginning of the 0.22 window instead of the last minute (or again miss it last minute).

@laanwj laanwj merged commit f1dbf92 into bitcoin:master Dec 18, 2020
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Dec 18, 2020
…ity checks

a0a7718 contrib: Changes to checks for PowerPC64 (Luke Dashjr)
634f6ec contrib: Parse ELF directly for symbol and security checks (Wladimir J. van der Laan)

Pull request description:

  Instead of the ever-messier text parsing of the output of the readelf tool (which is clearly meant for human consumption not to be machine parseable), parse the ELF binaries directly.

  Add a small dependency-less ELF parser specific to the checks.

  This is slightly more secure, too, because it removes potential ambiguity due to misparsing and changes in the output format of `elfread`. It also allows for stricter and more specific ELF format checks in the future.

  This removes the build-time dependency for `readelf`.

  It passes the test-security-check for me locally, ~~though I haven't checked on all platforms~~. I've checked that this works on the cross-compile output for all ELF platforms supported by Bitcoin Core at the moment, as well as PPC64 LE and BE.

Top commit has no ACKs.

Tree-SHA512: 7f9241fec83ee512642fecf5afd90546964561efd8c8c0f99826dcf6660604a4db2b7255e1afb1e9bb0211fd06f5dbad18a6175dfc03e39761a40025118e7bfc
laanwj added a commit that referenced this pull request Dec 28, 2020
1ef2138 lint: run mypy over contrib/devtools (fanquake)

Pull request description:

  wumpus mentioned on IRC that we don't currently run `mypy` over the `contrib/devtools` directory, and that it would likely be worthwhile given #20434. This just adds that dir to the linter, as well as some missing annotations to fix existing errors. Note that now we require Python 3.6 we can make use of variable annotations.

  master (patched to check contrib devtools):
  ```bash
  test/lint/lint-python.sh
  contrib/devtools/symbol-check.py:154: error: Incompatible types in assignment (expression has type "List[str]", variable has type "str")
  contrib/devtools/circular-dependencies.py:35: error: Need type annotation for 'deps' (hint: "deps: Dict[<type>, <type>] = ...")
  contrib/devtools/circular-dependencies.py:67: error: Need type annotation for 'closure' (hint: "closure: Dict[<type>, <type>] = ...")
  Found 4 errors in 3 files (checked 187 source files)
  ```

  I haven't quite gone as far as to add annotations like
  ```python
  CHECKS: Dict[str, List[Tuple[str, Callable[[Any], bool]]]] = {...
  ```
  to `symbol-check.py`.

ACKs for top commit:
  laanwj:
    ACK 1ef2138

Tree-SHA512: a58c2ece588c640289dc1d35dad5b1b8732788272daa0965d6bf44ee8a7f7c8e8585f94d233ac41c84b9ffcfc97841a00fe2c9acba41f58fd164f01de4b6512b
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Dec 28, 2020
1ef2138 lint: run mypy over contrib/devtools (fanquake)

Pull request description:

  wumpus mentioned on IRC that we don't currently run `mypy` over the `contrib/devtools` directory, and that it would likely be worthwhile given bitcoin#20434. This just adds that dir to the linter, as well as some missing annotations to fix existing errors. Note that now we require Python 3.6 we can make use of variable annotations.

  master (patched to check contrib devtools):
  ```bash
  test/lint/lint-python.sh
  contrib/devtools/symbol-check.py:154: error: Incompatible types in assignment (expression has type "List[str]", variable has type "str")
  contrib/devtools/circular-dependencies.py:35: error: Need type annotation for 'deps' (hint: "deps: Dict[<type>, <type>] = ...")
  contrib/devtools/circular-dependencies.py:67: error: Need type annotation for 'closure' (hint: "closure: Dict[<type>, <type>] = ...")
  Found 4 errors in 3 files (checked 187 source files)
  ```

  I haven't quite gone as far as to add annotations like
  ```python
  CHECKS: Dict[str, List[Tuple[str, Callable[[Any], bool]]]] = {...
  ```
  to `symbol-check.py`.

ACKs for top commit:
  laanwj:
    ACK 1ef2138

Tree-SHA512: a58c2ece588c640289dc1d35dad5b1b8732788272daa0965d6bf44ee8a7f7c8e8585f94d233ac41c84b9ffcfc97841a00fe2c9acba41f58fd164f01de4b6512b
laanwj added a commit that referenced this pull request Jan 28, 2021
543bf74 gitian-linux: Extend noexec-stack workaround to powerpc (Wladimir J. van der Laan)
00f67c8 gitian-linux: Build binaries for 64-bit POWER (Luke Dashjr)
63fc2b1 gitian: Properly quote arguments in wrappers (Luke Dashjr)
798bc0b Support glibc-back-compat on 64-bit POWER (Luke Dashjr)

Pull request description:

  Rebase of #14066 by luke-jr.

  Let's try to get PowerPC support in in the beginning of the 22.0 cycle so that it gets some testing, and is not a last-minute decision this time, like for last … 2 or 3 major versions.

  The symbol/security tooling-related changes have been dropped since they were part of #20434.

Top commit has no ACKs.

Tree-SHA512: df0f8cd320c90f359f8b512c5cb8b59bb277516b57a05482cc8923c656106513b7428e315aaa8ab53e0bd6f80556b07d3639c47f6d9913bcfbfe388b39ef47c4
@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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants