-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
unix: inconsistent handling of closed stdio #2962
Comments
I appreciate that you wrote up all that but what exactly are you proposing? For context: the philosophy that libuv adheres to is that closing file descriptors 0-2 is almost always a program bug, potentially with security implications: get the program to reopen them as sockets and the attacker can now read the program's logging. There are a few uses of |
Sorry for being unclear on this. What I'm proposing is to make things consistent. That is:
|
The existing code, especially the |
I think this is a duplicate of #2062. My comment there is that our experience in JuliaLang found that embedding applications (including nodejs) should pass |
@vtjnash It seems that #2062 is about libuv's behavior when it is given a stdio fd. However, I'm trying to address something different here: when stdio fds are closed outside of libuv 1) users may pass libuv fd 0-2 which is reused for other purposes 2) libuv itself may create fds with number 0-2 and crash due to assertion failure in |
Yep, that was a different example, but I'm suggesting it's the same underlying issue (that libuv shouldn't assume fd 0-2 are special numbers, and that users shouldn't pass stdio fd directly to libuv). |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
You know, this issue is still there, it is still causing random pain at surprising places (libuv being a library, after all). If libuv's take on FD0-2 being closed is that "it is broken", to the point of assert() crashing applications that get started through multiple layers of shell scripting that somehow ended up with, e.g., stdin closed... why doesn't it open a closed fd 0-2 to /dev/null? Either that, or drop the self-inflicting DoS caused by these asserts. For the record, here's what I end up adding to every application under my control, since libuv is not the only library out there that is broken re. FD 0-2 expectiations at program start (glibc FILE streams on non setuid/setgid applications being another high-profile example). I didn't know at the time I'd be working around libuv bugs with this, but... there you have it... not portable as is, but it should be possible to port it to windows, etc. static int is_valid_fd(const int fd) static void fix_fds(const int fd, const int fl) if (is_valid_fd(fd)) nfd = open("/dev/null", fl); /*
|
Yep, that is a good observation too. I let stale bot close this only because I consider it to be a duplicate of #2062, which I hope will be fixed here in v2. But even for v1, I think your code logic would be a useful addition to the libuv library as a new recommended initialization helper function if you would be interested in making a PR. Note, for github markdown comments, you can use code fences to make your code more readable like so:
|
Well, I don't know libuv (nor I use it currently), so it is unlikely I'd get to that PR anytime soon. If anyone else is interested in doing so, please feel free to do it. It is certainly something every POSIX application should do at startup in the general case. |
Currently different components of libuv behaves inconsistently when stdio fds are closed manually by user. joyent/libuv#943 introduced the check that will cause crash the whole program when attempting to close a fd <= 2. It assumes that normally libuv shall not try to close such fds, but it is not the case when a user chooses to manually close stdio fds, after which system will reuse these fd numbers when creating new fds.
Then there are changes trying to address such problems. #796 introduced
uv__close_nocheckstdio
forprocess.c
, which is later used in some other components. There's even a test case for closed stdio: fd77a5d (though it was added before the introduction ofuv__close
inprocess.c
)As a result, support for closed stdio is in a very inconsistent and confusing state. Most components of libuv will crash when stdio is closed manually, because users may pass it a low-numbered fd reused by system, or libuv itself may create low-numbered fds. In the meantime, there's a small number of functions that uses
uv__close_nocheckstdio
and will work in these edge cases.To make things worth, even these function are inconsistent. For example
uv_spawn
only callsuv__close_nocheckstdio
forsignal_pipe
but usesuv__close
for other things. So it will not fail when there's nothing inoptions->stdio
but will fail when both stdin and stdout is closed and user specifiesUV_CREATE_PIPE
inoptions->stdio
(addclose(1)
to thespawn_closed_process_io
test it will fail)The text was updated successfully, but these errors were encountered: