Skip to content

Conversation

luke-jr
Copy link
Member

@luke-jr luke-jr commented Jul 8, 2021

Currently, RunCommandParseJSON runs its target with whatever fds happen to be open inherited on POSIX platforms. I don't think there's any practical scenario where this is a problem right now, but there's a lot of potential for weird problems (eg, if a process manages to outlive bitcoind - perhaps it's hanging - the listening port(s) won't get released and starting bitcoind again will fail). It's also a potential security issue if a child process is intended to be sandboxed at some point. Not to mention plain ugly :)

Note that boost::process has a boost::process::limit_handles extension for this, but it requires a newer Boost and is even in the latest version still somewhat broken on Windows (where it probably doesn't matter since handle inheritance is off by default - but will execute undefined behaviour dereferencing/writing of an end-iterator): boostorg/process#200

Instead of closing directly, we have to set the FD_CLOEXEC flag and let exec close them; otherwise, boost::process's internal pipe would be closed and we get the wrong exception thrown (not actually a problem outside of our tests, but might as well do this cleanly).

@luke-jr luke-jr force-pushed the bpchild_closefds branch 4 times, most recently from ded64d7 to b7c45c8 Compare July 8, 2021 07:41
@fanquake fanquake requested a review from Sjors July 8, 2021 08:20
@luke-jr luke-jr force-pushed the bpchild_closefds branch from b7c45c8 to 3b6153b Compare July 8, 2021 18:29
@luke-jr luke-jr changed the title util/system: Close non-std fds before execing slave processes util/system: Close non-std fds when execing slave processes Jul 8, 2021
@tryphe
Copy link
Contributor

tryphe commented Aug 1, 2021

Concept ACK

Is it possible to easily test this functionality? I would like to give it a go.

@luke-jr
Copy link
Member Author

luke-jr commented Aug 1, 2021

Should be possible with a long-running process, then looking at /proc/*pid*/fd or such.

If you want to create a problem, write a program to write to random fd numbers (likely will corrupt things, don't try on an important node). :p

@Sjors
Copy link
Member

Sjors commented Aug 6, 2021

This is a bit beyond my understanding of processes. I tested (on macOS) that 3b6153b doesn't break HWI integration, so I have no objection.

void on_exec_setup(Executor&exec) const
{
try {
for (auto it : fs::directory_iterator("/dev/fd")) {
Copy link
Member

@laanwj laanwj Nov 29, 2021

Choose a reason for hiding this comment

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

TIL /dev/fd is a general UNIX thing and not limited to Linux. It doesn't seem like a very nice API to iterate open file descriptors but seems portable enough.

luke-jr added a commit to bitcoinknots/bitcoin that referenced this pull request Dec 14, 2021
@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 2, 2022

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

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK tryphe

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #29744 (lint: Refactor lint checks to reuse exclusion logic; Support running individual lint checks in lint runner by davidgumberg)
  • #28981 (Replace Boost.Process with cpp-subprocess by hebasto)

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.

@luke-jr luke-jr force-pushed the bpchild_closefds branch 2 times, most recently from 7b0c71c to 4c19cea Compare May 12, 2022 07:00
@Sjors
Copy link
Member

Sjors commented May 12, 2022

Compiling 4c19cea on macOS 12.3.1 (Boost 1.78 via Homebrew) fails with:

wallet/test/init_test_fixture.cpp:35:52: error: no member named 'BOOST_FILESYSTEM_C_STR' in 'boost::filesystem::path'
    std::ofstream f(m_walletdir_path_cases["file"].BOOST_FILESYSTEM_C_STR);
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
1 error generated.
make[2]: *** [wallet/test/test_test_bitcoin-init_test_fixture.o] Error 1

Compiling with depends does work.

Update: compiling on master @ 4129134 also fails, so this is unrelated (and already fixed, see #22482). Maybe rebase?

For some reason CI has not run yet on this PR (probably because it builds on top of commits that use a previous CI incarnation).

@luke-jr
Copy link
Member Author

luke-jr commented May 12, 2022

Testing and CI should always be merging the PR into master. The PR itself should ideally in the case of bugfixes like this, be based on the oldest affected commit (that can still cleanly merge, in Core's case)

@DrahtBot
Copy link
Contributor

🐙 This pull request conflicts with the target branch and needs rebase.

Want to unsubscribe from rebase notifications on this pull request? Just convert this pull request to a "draft".

@luke-jr luke-jr marked this pull request as ready for review July 5, 2023 16:15
@luke-jr luke-jr force-pushed the bpchild_closefds branch from 2255d3b to 60bc072 Compare July 5, 2023 16:15
@luke-jr
Copy link
Member Author

luke-jr commented Jul 5, 2023

Rebased and squashed

#include <fcntl.h>
#ifdef FD_CLOEXEC
#include <unistd.h>
#if defined(__GNUC__)
Copy link
Member

Choose a reason for hiding this comment

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

In-code warning suppression has recently been removed, so you can drop all of the #if defined(__GNUC__) blocks.

@maflcko
Copy link
Member

maflcko commented Apr 5, 2024

Are you still working on this? There has been no reply to a review comment for about a year: #22417 (comment)

@DrahtBot
Copy link
Contributor

🐙 This pull request conflicts with the target branch and needs rebase.

@fanquake
Copy link
Member

What is the status of this now that Boost Process is removed (given that this currently adds Boost Process code)?

@fanquake
Copy link
Member

Closing, see above, and this is adding Boost Process code, which no-longer exists in this codebase.

@fanquake fanquake closed this Jun 25, 2024
@Sjors
Copy link
Member

Sjors commented Jun 25, 2024

What is the status of this now that Boost Process is removed

For historical reference: this patch is no longer relevant, since #28981 replaced boost-process with cpp-subprocess.

@luke-jr does cpp-subprocess do anything similar that needs addressing? https://github.com/bitcoin/bitcoin/blob/master/src/util/subprocess.h

achow101 added a commit that referenced this pull request May 14, 2025
a0eed55 run_command: Enable close_fds option to avoid lingering fds (Luke Dashjr)
c7c356a cpp-subprocess: Iterate through /proc/self/fd for close_fds option on Linux (Luke Dashjr)
4f5e04d Revert "remove unneeded close_fds option from cpp-subprocess" (Luke Dashjr)

Pull request description:

  Picks up stale #30756, while addressing my fallback comment (#30756 (comment)).

  > Currently, RunCommandParseJSON runs its target with whatever fds happen to be open inherited on POSIX platforms. I don't think there's any practical scenario where this is a problem right now, but there's a lot of potential for weird problems (eg, if a process manages to outlive bitcoind - perhaps it's hanging - the listening port(s) won't get released and starting bitcoind again will fail). It's also a potential security issue if a child process is intended to be sandboxed at some point. Not to mention plain ugly :)
  >
  > cpp-subprocess has a feature to address this called close_fds. Not sure why it was removed in #29961 rather than fixing this during the migration, but this PR restores it, enables it for RunCommandParseJSON, and optimises it by iterating over /proc/self/fd/ like most other libraries do these days ([eg, glib]> (https://gitlab.gnome.org/GNOME/glib/blob/487b1fd20c5e494366a82ddc0fa6b53b8bd779ad/glib/gspawn.c#L1094)) since iterating all possible fd numbers [has been found to be problematic](https://bugzilla.redhat.com/show_bug.cgi?id=1537564).
  >
  > (Equivalent to #22417 was for boost::process)

ACKs for top commit:
  achow101:
    ACK a0eed55
  hebasto:
    ACK a0eed55, tested on Ubuntu 25.04:
  vasild:
    ACK a0eed55

Tree-SHA512: 7dc1cb6cc1f45ff7c4f53512e400baad1a033b4ebf14ba6f6ffa38588314932d6d01ef67b197f081e8202bb802659ac6a87998277797721d6d7b20efde8e9a6b
@bitcoin bitcoin locked and limited conversation to collaborators Jun 25, 2025
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.

8 participants