mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
utils: use safe procfs for /proc/self/fd loop code
From a safety perspective this might not be strictly required, but it paves the way for us to remove utils.ProcThreadSelf. Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
This commit is contained in:
@@ -86,6 +86,25 @@ func SetMempolicy(mode uint, mask *unix.CPUSet) error {
|
|||||||
return os.NewSyscallError("set_mempolicy", err)
|
return os.NewSyscallError("set_mempolicy", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Readlinkat wraps [unix.Readlinkat].
|
||||||
|
func Readlinkat(dir *os.File, path string) (string, error) {
|
||||||
|
size := 4096
|
||||||
|
for {
|
||||||
|
linkBuf := make([]byte, size)
|
||||||
|
n, err := retryOnEINTR2(func() (int, error) {
|
||||||
|
return unix.Readlinkat(int(dir.Fd()), path, linkBuf)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", &os.PathError{Op: "readlinkat", Path: dir.Name() + "/" + path, Err: err}
|
||||||
|
}
|
||||||
|
if n != size {
|
||||||
|
return string(linkBuf[:n]), nil
|
||||||
|
}
|
||||||
|
// Possible truncation, resize the buffer.
|
||||||
|
size *= 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetPtyPeer is a wrapper for ioctl(TIOCGPTPEER).
|
// GetPtyPeer is a wrapper for ioctl(TIOCGPTPEER).
|
||||||
func GetPtyPeer(ptyFd uintptr, unsafePeerPath string, flags int) (*os.File, error) {
|
func GetPtyPeer(ptyFd uintptr, unsafePeerPath string, flags int) (*os.File, error) {
|
||||||
// Make sure O_NOCTTY is always set -- otherwise runc might accidentally
|
// Make sure O_NOCTTY is always set -- otherwise runc might accidentally
|
||||||
|
|||||||
@@ -15,10 +15,11 @@ import (
|
|||||||
|
|
||||||
"github.com/opencontainers/cgroups"
|
"github.com/opencontainers/cgroups"
|
||||||
"github.com/opencontainers/cgroups/systemd"
|
"github.com/opencontainers/cgroups/systemd"
|
||||||
|
"github.com/opencontainers/runc/internal/linux"
|
||||||
|
"github.com/opencontainers/runc/internal/pathrs"
|
||||||
"github.com/opencontainers/runc/libcontainer"
|
"github.com/opencontainers/runc/libcontainer"
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
"github.com/opencontainers/runc/libcontainer/internal/userns"
|
"github.com/opencontainers/runc/libcontainer/internal/userns"
|
||||||
"github.com/opencontainers/runc/libcontainer/utils"
|
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
@@ -1683,11 +1684,9 @@ func TestFdLeaksSystemd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func fdList(t *testing.T) []string {
|
func fdList(t *testing.T) []string {
|
||||||
procSelfFd, closer := utils.ProcThreadSelf("fd")
|
fdDir, closer, err := pathrs.ProcThreadSelfOpen("fd/", unix.O_DIRECTORY|unix.O_CLOEXEC)
|
||||||
defer closer()
|
|
||||||
|
|
||||||
fdDir, err := os.Open(procSelfFd)
|
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
defer closer()
|
||||||
defer fdDir.Close()
|
defer fdDir.Close()
|
||||||
|
|
||||||
fds, err := fdDir.Readdirnames(-1)
|
fds, err := fdDir.Readdirnames(-1)
|
||||||
@@ -1726,8 +1725,10 @@ func testFdLeaks(t *testing.T, systemd bool) {
|
|||||||
|
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
procSelfFd, closer := utils.ProcThreadSelf("fd/")
|
procSelfFd, closer, err := pathrs.ProcThreadSelfOpen("fd/", unix.O_DIRECTORY|unix.O_CLOEXEC)
|
||||||
|
ok(t, err)
|
||||||
defer closer()
|
defer closer()
|
||||||
|
defer procSelfFd.Close()
|
||||||
|
|
||||||
next_fd:
|
next_fd:
|
||||||
for _, fd1 := range fds1 {
|
for _, fd1 := range fds1 {
|
||||||
@@ -1736,7 +1737,7 @@ next_fd:
|
|||||||
continue next_fd
|
continue next_fd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dst, _ := os.Readlink(filepath.Join(procSelfFd, fd1))
|
dst, _ := linux.Readlinkat(procSelfFd, fd1)
|
||||||
for _, ex := range excludedPaths {
|
for _, ex := range excludedPaths {
|
||||||
if ex == dst {
|
if ex == dst {
|
||||||
continue next_fd
|
continue next_fd
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
securejoin "github.com/cyphar/filepath-securejoin"
|
securejoin "github.com/cyphar/filepath-securejoin"
|
||||||
"github.com/opencontainers/runc/internal/linux"
|
"github.com/opencontainers/runc/internal/linux"
|
||||||
|
"github.com/opencontainers/runc/internal/pathrs"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
@@ -59,15 +60,15 @@ type fdFunc func(fd int)
|
|||||||
// fdRangeFrom calls the passed fdFunc for each file descriptor that is open in
|
// fdRangeFrom calls the passed fdFunc for each file descriptor that is open in
|
||||||
// the current process.
|
// the current process.
|
||||||
func fdRangeFrom(minFd int, fn fdFunc) error {
|
func fdRangeFrom(minFd int, fn fdFunc) error {
|
||||||
procSelfFd, closer := ProcThreadSelf("fd")
|
fdDir, closer, err := pathrs.ProcThreadSelfOpen("fd/", unix.O_DIRECTORY|unix.O_CLOEXEC)
|
||||||
defer closer()
|
|
||||||
|
|
||||||
fdDir, err := os.Open(procSelfFd)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("get handle to /proc/thread-self/fd: %w", err)
|
||||||
}
|
}
|
||||||
|
defer closer()
|
||||||
defer fdDir.Close()
|
defer fdDir.Close()
|
||||||
|
|
||||||
|
// NOTE: This is not really necessary since securejoin.ProcThreadSelf
|
||||||
|
// verifies this in a far stricter sense than EnsureProcHandle.
|
||||||
if err := EnsureProcHandle(fdDir); err != nil {
|
if err := EnsureProcHandle(fdDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
"github.com/opencontainers/runc/internal/pathrs"
|
||||||
"github.com/opencontainers/runc/libcontainer"
|
"github.com/opencontainers/runc/libcontainer"
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
"github.com/opencontainers/runc/libcontainer/specconv"
|
"github.com/opencontainers/runc/libcontainer/specconv"
|
||||||
@@ -241,10 +242,14 @@ func (r *runner) run(config *specs.Process) (int, error) {
|
|||||||
process.ExtraFiles = append(process.ExtraFiles, r.listenFDs...)
|
process.ExtraFiles = append(process.ExtraFiles, r.listenFDs...)
|
||||||
}
|
}
|
||||||
baseFd := 3 + len(process.ExtraFiles)
|
baseFd := 3 + len(process.ExtraFiles)
|
||||||
procSelfFd, closer := utils.ProcThreadSelf("fd/")
|
procSelfFd, closer, err := pathrs.ProcThreadSelfOpen("fd/", unix.O_DIRECTORY|unix.O_CLOEXEC)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
defer closer()
|
defer closer()
|
||||||
|
defer procSelfFd.Close()
|
||||||
for i := baseFd; i < baseFd+r.preserveFDs; i++ {
|
for i := baseFd; i < baseFd+r.preserveFDs; i++ {
|
||||||
_, err = os.Stat(filepath.Join(procSelfFd, strconv.Itoa(i)))
|
err := unix.Faccessat(int(procSelfFd.Fd()), strconv.Itoa(i), unix.F_OK, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, fmt.Errorf("unable to stat preserved-fd %d (of %d): %w", i-baseFd, r.preserveFDs, err)
|
return -1, fmt.Errorf("unable to stat preserved-fd %d (of %d): %w", i-baseFd, r.preserveFDs, err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user