-
Notifications
You must be signed in to change notification settings - Fork 238
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
Tidy up handling of intermediate pid fds #665
base: main
Are you sure you want to change the base?
Conversation
Both sockets in the socket pair are technically bidirectional, but we are using them as though they were unidirectional, with the same convention as pipe(): the first socket in the array is used for reading, and the second is for writing. Signed-off-by: Simon McVittie <smcv@collabora.com>
Instead of making this conditional and keeping track of the correct condition under which to call it, we can use cleanup_fdp(), which is a no-op when called with a pointer to a negative number, to close the socket unconditionally. In the parent bwrap monitor process (outside the sandbox), we never want to use the write end (which is reserved for the child), so we can and should close it as soon as we have forked. Conversely, in the child process, we never want to use the read end (which is reserved for the parent), so we should close that as soon as we know we are in the child. Signed-off-by: Simon McVittie <smcv@collabora.com>
This closes the fd and sets the variable to -1 as a single operation, which is easier to reason about because it does not leave any variables containing dangling references to invalid fds. Signed-off-by: Simon McVittie <smcv@collabora.com>
09169eb
to
1484a95
Compare
@@ -3143,12 +3143,12 @@ main (int argc, | |||
if (pid != 0) | |||
{ | |||
/* Parent, outside sandbox, privileged (initially) */ | |||
cleanup_fdp (&intermediate_pids_sockets[PIPE_WRITE_END]); |
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.
What about assigning -1
to the passe pointer in cleanup_fdp()
, so a potential second close()
call won't close an uninvolved descriptor.
For the cleanup attribute annotated variables compilers should be able to optimize the assignment out.
Another unrelated thought: systemd uses a safe_close()
wrapper instead of directly close(3)
to assert EBADF
was not returned, to spot file descriptor mixups, see https://github.com/systemd/systemd/blob/v256.7/src/basic/fd-util.c#L59.
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.
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.
This closes the fd and sets the variable to -1 as a single operation
[citation needed]
This avoids leaving dangling references to fds that no longer exist, clarifying ownership. This commit does not cover the socket pairs used to transfer the pid of a descendant process (see containers#665 for that) and privilege-separated operations (see containers#666). Signed-off-by: Simon McVittie <smcv@collabora.com>
GLib does similarly, in |
Use PIPE_READ_END, PIPE_WRITE_END to clarify use of a socketpair
Both sockets in the socket pair are technically bidirectional, but we
are using them as though they were unidirectional, with the same
convention as pipe(): the first socket in the array is used for reading,
and the second is for writing.
Close unused ends of intermediate_pids_sockets sooner
Instead of making this conditional and keeping track of the correct
condition under which to call it, we can use cleanup_fdp(), which is
a no-op when called with a pointer to a negative number, to close the
socket unconditionally.
In the parent bwrap monitor process (outside the sandbox), we never
want to use the write end (which is reserved for the child), so we
can and should close it as soon as we have forked.
Conversely, in the child process, we never want to use the read end
(which is reserved for the parent), so we should close that as soon
as we know we are in the child.
Use cleanup_fd to close intermediate pid sockets
This closes the fd and sets the variable to -1 as a single operation,
which is easier to reason about because it does not leave any variables
containing dangling references to invalid fds.
cc @refi64 @WGH- @mcatanzaro
I think #576 would have better clarity if it was rebased on this and used similar techniques. Reviews welcome, even from non-maintainers.