-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
fix an error caused by fd reuse race when starting runc init #4452
Conversation
dca6564
to
37302c5
Compare
Related: it would be nice to finish https://go-review.googlesource.com/c/go/+/515799 |
Yes, but this logic is very complex, maybe need more time to test. Another thing I want to know, the closed fd 6/7 is opened and closed by whom? I printed the first 6 fds:
Maybe by go runtime? |
37302c5
to
e502359
Compare
c9ed140
to
ddc70a3
Compare
There is a race situation when we are opening a file, if there is a small fd was closed at that time, maybe it will be reused by safeExe. Because of Go stdlib fds shuffling bug, if the fd of safeExe is too small, go stdlib will dup3 it to another fd, or dup3 a other fd to this fd, then it will cause the fd type cmd.Path refers to a random path, and it can lead to an error "permission denied" when starting the process. Please see opencontainers#4294 and <golang/go#61751>. So we should not use the original fd of safeExe, but use the fd after shuffled by Go stdlib. Because Go stdlib will guarantee this fd refers to the correct file. Signed-off-by: lfbzhm <[email protected]>
ddc70a3
to
e669926
Compare
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 solution is simpler than the previous one. It's still a bit ugly but at least we are using ExtraFiles
"properly" now.
I'll see if I have some time to rework the Go stdlib patch.
Yes, another ugly place: runc/libcontainer/container_linux.go Line 563 in e669926
We should set a correct valut to exePath at this line, but it's hard to move the patch code to this place. Because append some files to p.ExtraFiles will cause more problems.It indeed seems that it's the simplest way to fix the bug at this time. |
Yeah, it would be nice if Go supported |
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.
LGTM, thanks for fixing this nasty bug! I guess the debugging wasn't easy :D
// So we should not use the original fd of safeExe, but use the fd after | ||
// shuffled by Go stdlib. Because Go stdlib will guarantee this fd refers to | ||
// the correct file. | ||
cmd.Path = "/proc/self/fd/" + strconv.Itoa(stdioFdCount+len(cmd.ExtraFiles)-1) |
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.
Super nit: I think it would be slightly more clear if we add a comment here: https://github.com/opencontainers/runc/blob/main/libcontainer/container_linux.go#L563 saying we will override it later.
Also, IMHO having this in a function and just calling it from https://github.com/opencontainers/runc/blob/main/libcontainer/container_linux.go#L563 seems slightly better. But I don't know if it feels safer, due to this nasty bug, to do it way later when we won't have a small fd number (to be extra cautious).
In any case, this is very subjective and if the code as is feels better, I'm completely fine. And even if we want to add it, this can be a follow-up PR.
Fixes: #4294
There is a race situation when we are opening a file, if there is a
small fd was closed at that time, maybe it will be reused by safeExe.
Because of Go stdlib fds shuffling bug, if the fd of safeExe is too
small, go stdlib will dup3 it to another fd, or dup3 a other fd to this
fd, then it will cause the fd type cmd.Path refers to a random path,
and it can lead to an error "permission denied" when starting the process.
Please see #4294 and golang/go#61751.
So we should not use the original fd of safeExe, but use the fd after
shuffled by Go stdlib. Because Go stdlib will guarantee this fd refers to
the correct file.
Signed-off-by: lfbzhm [email protected]