From 5d4c05f0c3d7a6ae9f445765009558e109ba4d37 Mon Sep 17 00:00:00 2001 From: Nicolas Lacasse Date: Thu, 15 Dec 2022 14:17:48 -0800 Subject: [PATCH] Close specFile after reading it to avoid exposing the spec to the sandbox. PiperOrigin-RevId: 495694909 --- runsc/cmd/boot.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/runsc/cmd/boot.go b/runsc/cmd/boot.go index 63a502333..520b9c156 100644 --- a/runsc/cmd/boot.go +++ b/runsc/cmd/boot.go @@ -20,6 +20,7 @@ import ( "io/ioutil" "os" "os/exec" + "runtime" "runtime/debug" "strings" @@ -222,9 +223,10 @@ func (b *Boot) Execute(_ context.Context, f *flag.FlagSet, args ...any) subcomma } } - // Get the spec from the specFD. + // Get the spec from the specFD. We *must* keep this os.File alive past + // the call setCapsAndCallSelf, otherwise the FD will be closed and the + // child process cannot read it specFile := os.NewFile(uintptr(b.specFD), "spec file") - defer specFile.Close() spec, err := specutils.ReadSpecFromFile(b.bundleDir, specFile, conf) if err != nil { util.Fatalf("reading spec: %v", err) @@ -258,9 +260,19 @@ func (b *Boot) Execute(_ context.Context, f *flag.FlagSet, args ...any) subcomma // because the ReadSpecFromFile function seeks to the beginning // of the file before reading. util.Fatalf("setCapsAndCallSelf(%v, %v): %v", args, caps, setCapsAndCallSelf(args, caps)) + + // This prevents the specFile finalizer from running and closed + // the specFD, which we have passed to ourselves when + // re-execing. + runtime.KeepAlive(specFile) panic("unreachable") } + // Close specFile to avoid exposing it to the sandbox. + if err := specFile.Close(); err != nil { + util.Fatalf("closing specFile: %v", err) + } + // At this point we won't re-execute, so it's safe to limit via rlimits. Any // limit >= 0 works. If the limit is lower than the current number of open // files, then Setrlimit will succeed, and the next open will fail.