-
Notifications
You must be signed in to change notification settings - Fork 36
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
Close stdin / stdout / stderr in child process after fork #7
Conversation
This seems to be necessary to detach from the pseudo tty when running in background. I did the minimal change that seems to fix our issue, but other changes might be useful as well here (setsid, redirect stdout/stderr to /dev/null), etc.
I spent little time chasing this since #5, and considered your change before. The problem is that if you execute a file that does not exist, and stdout/stderr are closed, we don't get a chance to report errors. For example, before your change:
After your change:
So I guess there's more to look at. |
Thanks for the quick answer, I see the issue. If I get the code correctly, Out of curiosity I checked how debian's
So it seems (and I confirmed with strace) that it does a stat to check that the file exist, before forking. This is not bullet proof, if I create a file without execution permission, WDYT? I can do the change if you like the idea. The only other option that I can think of is to close the FDs after half a second or so, but that's a bit ugly, slows down SSH connections, and could lead to races. |
That's where I was going to, also. Do a Yeah go ahead and update the PR and let's move fwd. |
The check for exec permission needs to check against the user and group that we're going to run with.. perhaps that's why start-stop-daemon doesn't do it. :) edit: if we're restrictive based on that, we might fall into checking posix extended acls and all that jazz. |
Also check if it's executable. The check for executable succeeds if any of user, group or other has the x flag set. Note that this change means that the executable must be passed with the full path.
@fiorix I added another commit that does a stat on the file and checks if any of the executable flags are set. The check passes if any of the bits (user, group, other) is set. It still doesn't catch all possible permission errors, but I think the most common ones should be covered without false positives. There is a downside to this, though: you can no longer execute anything from |
That sucks. We can scan through $PATH and look for the file in it. I'm a bit rusty in C but I think this would do:
It needs an |
Although the comments say it checks the current directory, it doesn't. Needs that too. |
I wouldn't say it's that bad, since this is primarily meant to be used in init scripts, in which it's good practice to use absolute paths anyway. And it's easy to do I would be afraid of corner cases when looking for the executable in |
return 1; | ||
} | ||
if (!(exec_stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { | ||
fprintf(stderr, "file %s doesn't look executable\n", |
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.
Print Permission denied
instead.
Up to you, I'll probably put that in later on anyway. It's not too different from what execvp is doing except that they handle I've added a comment to your last commit to change the error message to the standard |
Thanks @fiorix, I pushed a fix for the err message. |
This patch caused problems with the logger thread. I've pushed another fix, which also addresses the security issues from other tickets. |
We use go-daemon in the Elastic Beats init scripts on the platforms that don't support systemd. We occasionally get reports about the init scripts failing when executed over SSH, usually via some deployment tool.
#5 seems related although not quite exactly what we experience. The easiest way to reproduce the problem is to run something like this:
SSH hangs for 10 seconds.
Closing FDs 0, 1, 2 on the first fork (the one for daemonizing the go-daemon process itself) seems necessary to detach from the pseudo tty when running in background. I did the minimal change that seems to fix our issue, but other changes might be useful as well here (setsid, redirect stdout/stderr to /dev/null), etc.