diff options
author | Nicolas Lacasse <nlacasse@google.com> | 2018-09-04 20:08:41 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-09-04 20:10:01 -0700 |
commit | ad8648c6343cf2cf3e51a0f58cb053ee303f6ffb (patch) | |
tree | 3b1c7c9e8d978258eee349592fd13fbebb36eb1e /runsc/cmd | |
parent | 2cff07381a911ad52cf9df70d702f39217e9539e (diff) |
runsc: Pass log and config files to sandbox process by FD.
This is a prereq for running the sandbox process as user "nobody", when it may
not have permissions to open these files.
Instead, we must open then before starting the sandbox process, and pass them
by FD.
The specutils.ReadSpecFromFile method was fixed to always seek to the beginning
of the file before reading. This allows Files from the same FD to be read
multiple times, as we do in the boot command when the apply-caps flag is set.
Tested with --network=host.
PiperOrigin-RevId: 211570647
Change-Id: I685be0a290aa7f70731ebdce82ebc0ebcc9d475c
Diffstat (limited to 'runsc/cmd')
-rw-r--r-- | runsc/cmd/boot.go | 19 | ||||
-rw-r--r-- | runsc/cmd/create.go | 3 | ||||
-rw-r--r-- | runsc/cmd/run.go | 3 |
3 files changed, 21 insertions, 4 deletions
diff --git a/runsc/cmd/boot.go b/runsc/cmd/boot.go index 666be902a..784baf23b 100644 --- a/runsc/cmd/boot.go +++ b/runsc/cmd/boot.go @@ -32,9 +32,12 @@ import ( // Boot implements subcommands.Command for the "boot" command which starts a // new sandbox. It should not be called directly. type Boot struct { - // bundleDir is the path to the bundle directory. + // bundleDir is the directory containing the OCI spec. bundleDir string + // specFD is the file descriptor that the spec will be read from. + specFD int + // controllerFD is the file descriptor of a stream socket for the // control server that is donated to this process. controllerFD int @@ -69,6 +72,7 @@ func (*Boot) Usage() string { // SetFlags implements subcommands.Command.SetFlags. func (b *Boot) SetFlags(f *flag.FlagSet) { f.StringVar(&b.bundleDir, "bundle", "", "required path to the root of the bundle directory") + f.IntVar(&b.specFD, "spec-fd", -1, "required fd with the container spec") f.IntVar(&b.controllerFD, "controller-fd", -1, "required FD of a stream socket for the control server that must be donated to this process") f.Var(&b.ioFDs, "io-fds", "list of FDs to connect 9P clients. They must follow this order: root first, then mounts as defined in the spec") f.BoolVar(&b.console, "console", false, "set to true if the sandbox should allow terminal ioctl(2) syscalls") @@ -78,7 +82,7 @@ func (b *Boot) SetFlags(f *flag.FlagSet) { // Execute implements subcommands.Command.Execute. It starts a sandbox in a // waiting state. func (b *Boot) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { - if b.bundleDir == "" || b.controllerFD == -1 || f.NArg() != 0 { + if b.specFD == -1 || b.controllerFD == -1 || f.NArg() != 0 { f.Usage() return subcommands.ExitUsageError } @@ -86,8 +90,10 @@ func (b *Boot) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) // Ensure that if there is a panic, all goroutine stacks are printed. debug.SetTraceback("all") - // Get the spec from the bundleDir. - spec, err := specutils.ReadSpec(b.bundleDir) + // Get the spec from the specFD. + specFile := os.NewFile(uintptr(b.specFD), "spec file") + defer specFile.Close() + spec, err := specutils.ReadSpecFromFile(b.bundleDir, specFile) if err != nil { Fatalf("error reading spec: %v", err) } @@ -123,6 +129,11 @@ func (b *Boot) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) args = append(args, arg) } } + + // Note that we've already read the spec from the spec FD, and + // we will read it again after the exec call. This works + // because the ReadSpecFromFile function seeks to the beginning + // of the file before reading. if err := setCapsAndCallSelf(args, caps); err != nil { Fatalf("%v", err) } diff --git a/runsc/cmd/create.go b/runsc/cmd/create.go index 94a889077..38ae03e7a 100644 --- a/runsc/cmd/create.go +++ b/runsc/cmd/create.go @@ -15,6 +15,8 @@ package cmd import ( + "path/filepath" + "context" "flag" "github.com/google/subcommands" @@ -83,6 +85,7 @@ func (c *Create) Execute(_ context.Context, f *flag.FlagSet, args ...interface{} Fatalf("error reading spec: %v", err) } specutils.LogSpec(spec) + conf.SpecFile = filepath.Join(bundleDir, "config.json") // Create the container. A new sandbox will be created for the // container unless the metadata specifies that it should be run in an diff --git a/runsc/cmd/run.go b/runsc/cmd/run.go index 681112f30..92aa6bc40 100644 --- a/runsc/cmd/run.go +++ b/runsc/cmd/run.go @@ -15,6 +15,7 @@ package cmd import ( + "path/filepath" "syscall" "context" @@ -71,6 +72,8 @@ func (r *Run) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) s if err != nil { Fatalf("error reading spec: %v", err) } + specutils.LogSpec(spec) + conf.SpecFile = filepath.Join(bundleDir, "config.json") ws, err := container.Run(id, spec, conf, bundleDir, r.consoleSocket, r.pidFile) if err != nil { |