Skip to content

Commit 8454bbb

Browse files
authored
Merge pull request #4175 from cyphar/fd-file-switch
init: use *os.File for passed file descriptors
2 parents 2dfc2fe + 7094efb commit 8454bbb

File tree

5 files changed

+33
-24
lines changed

5 files changed

+33
-24
lines changed

libcontainer/init_linux.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -141,24 +141,26 @@ func startInitialization() (retErr error) {
141141
logrus.SetLevel(logrus.Level(logLevel))
142142
}
143143

144-
logFD, err := strconv.Atoi(os.Getenv("_LIBCONTAINER_LOGPIPE"))
144+
logFd, err := strconv.Atoi(os.Getenv("_LIBCONTAINER_LOGPIPE"))
145145
if err != nil {
146146
return fmt.Errorf("unable to convert _LIBCONTAINER_LOGPIPE: %w", err)
147147
}
148+
logPipe := os.NewFile(uintptr(logFd), "logpipe")
148149

149-
logrus.SetOutput(os.NewFile(uintptr(logFD), "logpipe"))
150+
logrus.SetOutput(logPipe)
150151
logrus.SetFormatter(new(logrus.JSONFormatter))
151152
logrus.Debug("child process in init()")
152153

153154
// Only init processes have FIFOFD.
154-
fifofd := -1
155+
var fifoFile *os.File
155156
envInitType := os.Getenv("_LIBCONTAINER_INITTYPE")
156157
it := initType(envInitType)
157158
if it == initStandard {
158-
envFifoFd := os.Getenv("_LIBCONTAINER_FIFOFD")
159-
if fifofd, err = strconv.Atoi(envFifoFd); err != nil {
159+
fifoFd, err := strconv.Atoi(os.Getenv("_LIBCONTAINER_FIFOFD"))
160+
if err != nil {
160161
return fmt.Errorf("unable to convert _LIBCONTAINER_FIFOFD: %w", err)
161162
}
163+
fifoFile = os.NewFile(uintptr(fifoFd), "initfifo")
162164
}
163165

164166
var consoleSocket *os.File
@@ -212,10 +214,10 @@ func startInitialization() (retErr error) {
212214
}
213215

214216
// If init succeeds, it will not return, hence none of the defers will be called.
215-
return containerInit(it, &config, syncPipe, consoleSocket, pidfdSocket, fifofd, logFD, dmzExe)
217+
return containerInit(it, &config, syncPipe, consoleSocket, pidfdSocket, fifoFile, logPipe, dmzExe)
216218
}
217219

218-
func containerInit(t initType, config *initConfig, pipe *syncSocket, consoleSocket, pidfdSocket *os.File, fifoFd, logFd int, dmzExe *os.File) error {
220+
func containerInit(t initType, config *initConfig, pipe *syncSocket, consoleSocket, pidfdSocket, fifoFile, logPipe, dmzExe *os.File) error {
219221
if err := populateProcessEnvironment(config.Env); err != nil {
220222
return err
221223
}
@@ -227,7 +229,7 @@ func containerInit(t initType, config *initConfig, pipe *syncSocket, consoleSock
227229
consoleSocket: consoleSocket,
228230
pidfdSocket: pidfdSocket,
229231
config: config,
230-
logFd: logFd,
232+
logPipe: logPipe,
231233
dmzExe: dmzExe,
232234
}
233235
return i.Init()
@@ -238,8 +240,8 @@ func containerInit(t initType, config *initConfig, pipe *syncSocket, consoleSock
238240
pidfdSocket: pidfdSocket,
239241
parentPid: unix.Getppid(),
240242
config: config,
241-
fifoFd: fifoFd,
242-
logFd: logFd,
243+
fifoFile: fifoFile,
244+
logPipe: logPipe,
243245
dmzExe: dmzExe,
244246
}
245247
return i.Init()

libcontainer/mount_linux.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,12 @@ func mountViaFds(source string, srcFile *mountSource, target, dstFd, fstype stri
113113
// mount(2), we need to get a safe handle to /proc/thread-self. This
114114
// isn't needed for move_mount(2) because in that case the path is just
115115
// a dummy string used for error info.
116-
fdStr := strconv.Itoa(int(srcFile.file.Fd()))
116+
srcFileFd := srcFile.file.Fd()
117117
if isMoveMount {
118-
src = "/proc/self/fd/" + fdStr
118+
src = "/proc/self/fd/" + strconv.Itoa(int(srcFileFd))
119119
} else {
120120
var closer utils.ProcThreadSelfCloser
121-
src, closer = utils.ProcThreadSelf("fd/" + fdStr)
121+
src, closer = utils.ProcThreadSelfFd(srcFileFd)
122122
defer closer()
123123
}
124124
}

libcontainer/setns_init_linux.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"os"
77
"os/exec"
8-
"strconv"
98

109
"github.com/opencontainers/selinux/go-selinux"
1110
"github.com/sirupsen/logrus"
@@ -24,7 +23,7 @@ type linuxSetnsInit struct {
2423
consoleSocket *os.File
2524
pidfdSocket *os.File
2625
config *initConfig
27-
logFd int
26+
logPipe *os.File
2827
dmzExe *os.File
2928
}
3029

@@ -131,8 +130,8 @@ func (l *linuxSetnsInit) Init() error {
131130

132131
// Close the log pipe fd so the parent's ForwardLogs can exit.
133132
logrus.Debugf("setns_init: about to exec")
134-
if err := unix.Close(l.logFd); err != nil {
135-
return &os.PathError{Op: "close log pipe", Path: "fd " + strconv.Itoa(l.logFd), Err: err}
133+
if err := l.logPipe.Close(); err != nil {
134+
return fmt.Errorf("close log pipe: %w", err)
136135
}
137136

138137
if l.dmzExe != nil {

libcontainer/standard_init_linux.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"os"
77
"os/exec"
8-
"strconv"
98

109
"github.com/opencontainers/runtime-spec/specs-go"
1110
"github.com/opencontainers/selinux/go-selinux"
@@ -25,8 +24,8 @@ type linuxStandardInit struct {
2524
consoleSocket *os.File
2625
pidfdSocket *os.File
2726
parentPid int
28-
fifoFd int
29-
logFd int
27+
fifoFile *os.File
28+
logPipe *os.File
3029
dmzExe *os.File
3130
config *initConfig
3231
}
@@ -244,11 +243,11 @@ func (l *linuxStandardInit) Init() error {
244243

245244
// Close the log pipe fd so the parent's ForwardLogs can exit.
246245
logrus.Debugf("init: about to wait on exec fifo")
247-
if err := unix.Close(l.logFd); err != nil {
248-
return &os.PathError{Op: "close log pipe", Path: "fd " + strconv.Itoa(l.logFd), Err: err}
246+
if err := l.logPipe.Close(); err != nil {
247+
return fmt.Errorf("close log pipe: %w", err)
249248
}
250249

251-
fifoPath, closer := utils.ProcThreadSelf("fd/" + strconv.Itoa(l.fifoFd))
250+
fifoPath, closer := utils.ProcThreadSelfFd(l.fifoFile.Fd())
252251
defer closer()
253252

254253
// Wait for the FIFO to be opened on the other side before exec-ing the
@@ -269,7 +268,7 @@ func (l *linuxStandardInit) Init() error {
269268
// N.B. the core issue itself (passing dirfds to the host filesystem) has
270269
// since been resolved.
271270
// https://github.com/torvalds/linux/blob/v4.9/fs/exec.c#L1290-L1318
272-
_ = unix.Close(l.fifoFd)
271+
_ = l.fifoFile.Close()
273272

274273
s := l.config.SpecState
275274
s.Pid = unix.Getpid()

libcontainer/utils/utils_unix.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,12 @@ func ProcThreadSelf(subpath string) (string, ProcThreadSelfCloser) {
202202
}
203203
return threadSelf + subpath, runtime.UnlockOSThread
204204
}
205+
206+
// ProcThreadSelfFd is small wrapper around ProcThreadSelf to make it easier to
207+
// create a /proc/thread-self handle for given file descriptor.
208+
//
209+
// It is basically equivalent to ProcThreadSelf(fmt.Sprintf("fd/%d", fd)), but
210+
// without using fmt.Sprintf to avoid unneeded overhead.
211+
func ProcThreadSelfFd(fd uintptr) (string, ProcThreadSelfCloser) {
212+
return ProcThreadSelf("fd/" + strconv.FormatUint(uint64(fd), 10))
213+
}

0 commit comments

Comments
 (0)