*: switch to safer securejoin.Reopen

filepath-securejoin v0.3 gave us a much safer re-open primitive, we
should use it to avoid any theoretical attacks. Rather than using it
direcly, add a small pathrs wrapper to make libpathrs migrations in the
future easier...

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
This commit is contained in:
Aleksa Sarai
2025-06-19 10:19:41 +10:00
parent 6fc1914491
commit ff94f9991b
3 changed files with 39 additions and 8 deletions
+7 -7
View File
@@ -12,6 +12,7 @@ import (
"golang.org/x/sys/unix"
"github.com/opencontainers/runc/internal/linux"
"github.com/opencontainers/runc/internal/pathrs"
"github.com/opencontainers/runc/libcontainer/apparmor"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/keys"
@@ -259,19 +260,17 @@ func (l *linuxStandardInit) Init() error {
return fmt.Errorf("close log pipe: %w", err)
}
fifoPath, closer := utils.ProcThreadSelfFd(l.fifoFile.Fd())
defer closer()
// Wait for the FIFO to be opened on the other side before exec-ing the
// user process. We open it through /proc/self/fd/$fd, because the fd that
// was given to us was an O_PATH fd to the fifo itself. Linux allows us to
// re-open an O_PATH fd through /proc.
fd, err := linux.Open(fifoPath, unix.O_WRONLY|unix.O_CLOEXEC, 0)
fifoFile, err := pathrs.Reopen(l.fifoFile, unix.O_WRONLY|unix.O_CLOEXEC)
if err != nil {
return err
return fmt.Errorf("reopen exec fifo: %w", err)
}
if _, err := unix.Write(fd, []byte("0")); err != nil {
return &os.PathError{Op: "write exec fifo", Path: fifoPath, Err: err}
defer fifoFile.Close()
if _, err := fifoFile.Write([]byte("0")); err != nil {
return &os.PathError{Op: "write exec fifo", Path: fifoFile.Name(), Err: err}
}
// Close the O_PATH fifofd fd before exec because the kernel resets
@@ -280,6 +279,7 @@ func (l *linuxStandardInit) Init() error {
// N.B. the core issue itself (passing dirfds to the host filesystem) has
// since been resolved.
// https://github.com/torvalds/linux/blob/v4.9/fs/exec.c#L1290-L1318
_ = fifoFile.Close()
_ = l.fifoFile.Close()
if s := l.config.SpecState; s != nil {