Skip to content
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

Rework miral::launch_app_env() to avoid calling functions that are not async-signal-safe after fork() #3591

Merged
merged 3 commits into from
Sep 11, 2024

Conversation

AlanGriffiths
Copy link
Collaborator

Fixes: #3494

@AlanGriffiths AlanGriffiths requested a review from a team as a code owner September 9, 2024 10:36
Copy link
Contributor

@mattkae mattkae left a comment

Choose a reason for hiding this comment

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

Is the problem with this that when you fork, the environment that you established isn't necessarily maintained?

Copy link
Contributor

@RAOF RAOF left a comment

Choose a reason for hiding this comment

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

So, I think this is still wrong, but I'm approving anyway because it's a strict improvement and the correct thing is wild.

Feel free to do the correct thing, or merge this as an improvement.

src/miral/launch_app.cpp Outdated Show resolved Hide resolved
mir::log_debug("Restoring sigmask");
sigset_t all_signals;
sigfillset(&all_signals);
pthread_sigmask(SIG_UNBLOCK, &all_signals, nullptr);

execvp(exec_args[0], const_cast<char*const*>(exec_args.data()));
execvpe(exec_args[0], const_cast<char*const*>(exec_args.data()), const_cast<char*const*>(exec_env.data()));
Copy link
Contributor

Choose a reason for hiding this comment

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

execvpe,sadly, isn't async-signal-safe (presumably because the obvious implementation requires memory allocation?).

I believe the correct approach here is to do $PATH handling ourselves; pre-construct all the possible paths that would be searched through, and then in the child calling execve on each in turn, annoyingly needing to keep track of error returns.

What a faff!

Copy link
Contributor

Choose a reason for hiding this comment

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

For added bonus giggles, if $PATH is unset, we should be looking in _CS_PATH. Dear lord!

Copy link
Contributor

Choose a reason for hiding this comment

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

(For the record, none of the exec*p* functions are async-signal-safe)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What a faff!

Indeed. This is something that library implementers could (and should) get right for the rest of us

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't think there's a need for memory allocation in "the obvious implementation": remember C99 has VLAs. (See https://codebrowser.dev/glibc/glibc/posix/execvpe.c.html for an example implementation.)

So requiring execvpe() to be async-signal-safe is plausible (but outside our authority).

@RAOF
Copy link
Contributor

RAOF commented Sep 10, 2024

Is the problem with this that when you fork, the environment that you established isn't necessarily maintained?

The problem is that when you call fork, other threads are in an unknown state¹, in much the same way as in a signal handler, so you can't call anything that isn't async-signal-safe.

¹: Notably, they may have taken any number of internal libc locks, which will never be released in the child because the while the state of everything is duplicated only one thread of execution is forked by fork().

Copy link
Contributor

@mattkae mattkae left a comment

Choose a reason for hiding this comment

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

I am still okay with this, but I will leave it up to @RAOF to do the final merge, since he had the one concern about execvpe that he might want to check out.

@AlanGriffiths AlanGriffiths added this pull request to the merge queue Sep 11, 2024
Merged via the queue into main with commit 2ef1ecf Sep 11, 2024
25 of 26 checks passed
@AlanGriffiths AlanGriffiths deleted the launch_app_env branch September 11, 2024 10:27
@AlanGriffiths AlanGriffiths mentioned this pull request Sep 23, 2024
Saviq pushed a commit that referenced this pull request Sep 23, 2024
Saviq pushed a commit that referenced this pull request Sep 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Our fork/exec spawning is unsafe
3 participants