Skip to content

Commit e00eadd

Browse files
author
Michael Crosby
committed
Merge pull request docker-archive#17 from alexlarsson/fix-close-race
Fix invalid fd race
2 parents 4145356 + f602821 commit e00eadd

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

namespaces/init.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,10 @@ func setupRoute(container *libcontainer.Container) error {
185185
// and working dir, and closes any leaky file descriptors
186186
// before execing the command inside the namespace
187187
func FinalizeNamespace(container *libcontainer.Container) error {
188-
if err := system.CloseFdsFrom(3); err != nil {
188+
// Ensure that all non-standard fds we may have accidentally
189+
// inherited are marked close-on-exec so they stay out of the
190+
// container
191+
if err := utils.CloseExecFrom(3); err != nil {
189192
return fmt.Errorf("close open file descriptors %s", err)
190193
}
191194

@@ -217,6 +220,7 @@ func FinalizeNamespace(container *libcontainer.Container) error {
217220
return fmt.Errorf("chdir to %s %s", container.WorkingDir, err)
218221
}
219222
}
223+
220224
return nil
221225
}
222226

utils/utils.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import (
44
"crypto/rand"
55
"encoding/hex"
66
"io"
7+
"io/ioutil"
78
"path/filepath"
9+
"strconv"
10+
"syscall"
811
)
912

1013
// GenerateRandomName returns a new name joined with a prefix. This size
@@ -26,3 +29,27 @@ func ResolveRootfs(uncleanRootfs string) (string, error) {
2629
}
2730
return filepath.EvalSymlinks(rootfs)
2831
}
32+
33+
func CloseExecFrom(minFd int) error {
34+
fdList, err := ioutil.ReadDir("/proc/self/fd")
35+
if err != nil {
36+
return err
37+
}
38+
for _, fi := range fdList {
39+
fd, err := strconv.Atoi(fi.Name())
40+
if err != nil {
41+
// ignore non-numeric file names
42+
continue
43+
}
44+
45+
if fd < minFd {
46+
// ignore descriptors lower than our specified minimum
47+
continue
48+
}
49+
50+
// intentionally ignore errors from syscall.CloseOnExec
51+
syscall.CloseOnExec(fd)
52+
// the cases where this might fail are basically file descriptors that have already been closed (including and especially the one that was created when ioutil.ReadDir did the "opendir" syscall)
53+
}
54+
return nil
55+
}

0 commit comments

Comments
 (0)