Skip to content

syscall/plan9: remove spooky fd action at a distance #43533

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

Closed
wants to merge 1 commit into from

Conversation

oridb
Copy link
Contributor

@oridb oridb commented Jan 6, 2021

Change Plan 9 fork/exec to use the O_CLOEXEC file
descriptor, instead of relying on spooky at a
distance.

Historically, Plan 9 has set the O_CLOEXEC flag on
the underlying channels in the kernel, rather
than the file descriptors -- if two fds pointed
at a single channel, as with dup, changing the
flags on one of them would be observable on the
other.

The per-Chan semantics are ok, if unexpected,
when a chan is only handled within a single
process, but this isn't always the case.

Forked processes share Chans, but even more of
a problem is the interaction between /srv and
OCEXEC, which can lead to unexectedly closed
file descriptors in completely unrelated
proceses. For example:

func exists() bool {
	// If some other thread execs here,
	// we don't want to leak the fd, so
	// open it O_CLOEXEC
	fd := Open("/srv/foo", O_CLOEXEC)
	if fd != -1 {
		Close(fd)
		return true
	}
	return false
}

would close the connection to any file descriptor
(maybe even for the root fs) in ALL other processes
that have it open if an exec were to happen(!),
which is quite undesriable.

As a result, 9front will be changing this behavior
for the next release.

Go is the only code observed so far that relies on
this behavior on purpose, and It's easy to make the
code work with both semantics: simply using the file
descriptor that was opened with O_CEXEC instead of
throwing it away.

So we do that here.

Fixes #43524

Change Plan 9 fork/exec to use the O_CLOEXEC file
descriptor, instead of relying on spooky at a
distance.

Historically, Plan 9 has set the O_CLOEXEC flag on
the underlying channels in the kernel, rather
than the file descriptors -- if two fds pointed
at a single channel, as with dup, changing the
flags on one of them would be observable on the
other.

The per-Chan semantics are ok, if unexpected,
when a chan is only handled within a single
process, but this isn't always the case.

Forked processes share Chans, but even more of
a problem is the interaction between /srv and
OCEXEC, which can lead to unexectedly closed
file descriptors in completely unrelated
proceses. For example:

	func exists() bool {
		// If some other thread execs here,
		// we don't want to leak the fd, so
		// open it O_CLOEXEC
		fd := Open("/srv/foo", O_CLOEXEC)
		if fd != -1 {
			Close(fd)
			return true
		}
		return false
	}

would close the connection to any file descriptor
(maybe even for the root fs) in ALL other processes
that have it open if an exec were to happen(!),
which is quite undesriable.

As a result, 9front will be changing this behavior
for the next release.

Go is the only code observed so far that relies on
this behavior on purpose, and  It's easy to make the
code work with both semantics: simply using the file
descriptor that was opened with O_CEXEC instead of
throwing it away.

So we do that here.
@google-cla
Copy link

google-cla bot commented Jan 6, 2021

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it! and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@google-cla google-cla bot added the cla: no Used by googlebot to label PRs as having an invalid CLA. The text of this label should not change. label Jan 6, 2021
@oridb
Copy link
Contributor Author

oridb commented Jan 6, 2021

@googlebot I signed it!

@google-cla google-cla bot added cla: yes Used by googlebot to label PRs as having a valid CLA. The text of this label should not change. and removed cla: no Used by googlebot to label PRs as having an invalid CLA. The text of this label should not change. labels Jan 6, 2021
@gopherbot
Copy link
Contributor

This PR (HEAD: 96bb21b) has been imported to Gerrit for code review.

Please visit https://go-review.googlesource.com/c/go/+/281833 to see it.

Tip: You can toggle comments from me using the comments slash command (e.g. /comments off)
See the Wiki page for more info

@gopherbot
Copy link
Contributor

Message from Go Bot:

Patch Set 1:

Congratulations on opening your first change. Thank you for your contribution!

Next steps:
A maintainer will review your change and provide feedback. See
https://golang.org/doc/contribute.html#review for more info and tips to get your
patch through code review.

Most changes in the Go project go through a few rounds of revision. This can be
surprising to people new to the project. The careful, iterative review process
is our way of helping mentor contributors and ensuring that their contributions
have a lasting impact.

During May-July and Nov-Jan the Go project is in a code freeze, during which
little code gets reviewed or merged. If a reviewer responds with a comment like
R=go1.11 or adds a tag like "wait-release", it means that this CL will be
reviewed as part of the next development cycle. See https://golang.org/s/release
for more details.


Please don’t reply on this GitHub thread. Visit golang.org/cl/281833.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

Message from David du Colombier:

Patch Set 1: Run-TryBot+1 Code-Review+2

(1 comment)


Please don’t reply on this GitHub thread. Visit golang.org/cl/281833.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

Message from Go Bot:

Patch Set 1:

SlowBots beginning. Status page: https://farmer.golang.org/try?commit=7020cd33


Please don’t reply on this GitHub thread. Visit golang.org/cl/281833.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

Message from Go Bot:

Patch Set 1: TryBot-Result-1

1 of 22 SlowBots failed:
Failed on plan9-arm: https://storage.googleapis.com/go-build-log/7020cd33/plan9-arm_0adc1772.log

Consult https://build.golang.org/ to see whether they are new failures. Keep in mind that TryBots currently test exactly your git commit, without rebasing. If your commit's git parent is old, the failure might've already been fixed.

SlowBot builds that ran:

  • plan9-arm

Please don’t reply on this GitHub thread. Visit golang.org/cl/281833.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

Message from Ori Bernstein:

Patch Set 1:

(1 comment)


Please don’t reply on this GitHub thread. Visit golang.org/cl/281833.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

Message from Ian Lance Taylor:

Patch Set 1: Trust+1


Please don’t reply on this GitHub thread. Visit golang.org/cl/281833.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

Message from Richard Miller:

Patch Set 1: Code-Review+1

(1 comment)


Please don’t reply on this GitHub thread. Visit golang.org/cl/281833.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

Message from Jacob Moody:

Patch Set 1: Code-Review+1

(1 comment)


Please don’t reply on this GitHub thread. Visit golang.org/cl/281833.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

This PR is being closed because golang.org/cl/281833 has been merged.

@gopherbot gopherbot closed this Feb 8, 2021
pull bot pushed a commit to Pandinosaurus/go that referenced this pull request Feb 8, 2021
Change Plan 9 fork/exec to use the O_CLOEXEC file
descriptor, instead of relying on spooky at a
distance.

Historically, Plan 9 has set the O_CLOEXEC flag on
the underlying channels in the kernel, rather
than the file descriptors -- if two fds pointed
at a single channel, as with dup, changing the
flags on one of them would be observable on the
other.

The per-Chan semantics are ok, if unexpected,
when a chan is only handled within a single
process, but this isn't always the case.

Forked processes share Chans, but even more of
a problem is the interaction between /srv and
OCEXEC, which can lead to unexectedly closed
file descriptors in completely unrelated
proceses. For example:

	func exists() bool {
		// If some other thread execs here,
		// we don't want to leak the fd, so
		// open it O_CLOEXEC
		fd := Open("/srv/foo", O_CLOEXEC)
		if fd != -1 {
			Close(fd)
			return true
		}
		return false
	}

would close the connection to any file descriptor
(maybe even for the root fs) in ALL other processes
that have it open if an exec were to happen(!),
which is quite undesriable.

As a result, 9front will be changing this behavior
for the next release.

Go is the only code observed so far that relies on
this behavior on purpose, and  It's easy to make the
code work with both semantics: simply using the file
descriptor that was opened with O_CEXEC instead of
throwing it away.

So we do that here.

Fixes golang#43524

Change-Id: I4887f5c934a5e63e5e6c1bb59878a325abc928d3
GitHub-Last-Rev: 96bb21b
GitHub-Pull-Request: golang#43533
Reviewed-on: https://go-review.googlesource.com/c/go/+/281833
Reviewed-by: David du Colombier <[email protected]>
Reviewed-by: Richard Miller <[email protected]>
Reviewed-by: Jacob Moody <[email protected]>
Run-TryBot: David du Colombier <[email protected]>
Trust: Ian Lance Taylor <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Used by googlebot to label PRs as having a valid CLA. The text of this label should not change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

os/exec: program hangs if it reads from pipe on Plan 9 (9front)
2 participants