summaryrefslogtreecommitdiffhomepage
path: root/runsc/fsgofer/control.go
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2018-08-27 11:09:06 -0700
committerShentubot <shentubot@google.com>2018-08-27 11:10:14 -0700
commitdb81c0b02f2f947ae837a3e16471a148a66436eb (patch)
treed91ef12da80b0a76ef1c69db290665e31cc59860 /runsc/fsgofer/control.go
parent2524111fc63343fd7372f5ea0266130adea778a5 (diff)
Put fsgofer inside chroot
Now each container gets its own dedicated gofer that is chroot'd to the rootfs path. This is done to add an extra layer of security in case the gofer gets compromised. PiperOrigin-RevId: 210396476 Change-Id: Iba21360a59dfe90875d61000db103f8609157ca0
Diffstat (limited to 'runsc/fsgofer/control.go')
-rw-r--r--runsc/fsgofer/control.go204
1 files changed, 0 insertions, 204 deletions
diff --git a/runsc/fsgofer/control.go b/runsc/fsgofer/control.go
deleted file mode 100644
index 8cb2f67ac..000000000
--- a/runsc/fsgofer/control.go
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2018 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package fsgofer
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "sync"
-
- "gvisor.googlesource.com/gvisor/pkg/control/server"
- "gvisor.googlesource.com/gvisor/pkg/log"
- "gvisor.googlesource.com/gvisor/pkg/p9"
- "gvisor.googlesource.com/gvisor/pkg/unet"
- "gvisor.googlesource.com/gvisor/pkg/urpc"
-)
-
-// Controller manages the fsgofer's control server.
-type Controller struct {
- // api holds the control server's URPC endpoints.
- api api
-
- // srv is the control server.
- srv *server.Server
-}
-
-// NewController creates a new Controller and starts it listenting
-func NewController(fd int, rootBundleDir string) (*Controller, error) {
- if !filepath.IsAbs(rootBundleDir) {
- return nil, fmt.Errorf("NewController should receive an absolute bundle dir path, but got %q", rootBundleDir)
- }
-
- srv, err := server.CreateFromFD(fd)
- if err != nil {
- return nil, err
- }
-
- cr := &Controller{srv: srv}
- cr.api.rootBundleDir = rootBundleDir
- cr.api.bundleDirs = make(map[string]string)
- srv.Register(&cr.api)
-
- if err := srv.StartServing(); err != nil {
- return nil, err
- }
-
- return cr, nil
-}
-
-// Wait waits for all the p9 servers to finish, then shuts down the control
-// server.
-func (cr *Controller) Wait() {
- cr.api.p9wg.Wait()
- cr.srv.Stop()
- log.Infof("All 9P servers exited.")
-}
-
-// Serve starts serving each Attacher in ats via its corresponding file
-// descriptor in ioFDs. This takes ownership of the FDs in ioFDs.
-func (cr *Controller) Serve(ats []p9.Attacher, ioFDs []int) error {
- if len(ats) != len(ioFDs) {
- return fmt.Errorf("number of attach points does not match the number of IO FDs (%d and %d)", len(ats), len(ioFDs))
- }
- for i, _ := range ats {
- cr.api.serve(ats[i], os.NewFile(uintptr(ioFDs[i]), "io fd"))
- }
- return nil
-}
-
-// api URPC methods.
-const (
- // AddBundleDirs readies the gofer to serve from a new bundle
- // directory. It should be called during runsc create.
- AddBundleDirs = "api.AddBundleDirs"
-
- // ServeDirectory serves a new directory via the fsgofer. It should be
- // called during runsc start.
- ServeDirectory = "api.ServeDirectory"
-)
-
-// API defines and implements the URPC endpoints for the gofer.
-type api struct {
- // p9wg waits for all the goroutines serving the sentry via p9. When its
- // counter is 0, the gofer is out of work and exits.
- p9wg sync.WaitGroup
-
- // bundleDirs maps from container ID to bundle directory for each
- // container.
- bundleDirs map[string]string
-
- // rootBundleDir is the bundle directory of the root container.
- rootBundleDir string
-}
-
-// AddBundleDirsRequest is the URPC argument to AddBundleDirs.
-type AddBundleDirsRequest struct {
- // BundleDirs is a map of container IDs to bundle directories to add to
- // the gofer.
- BundleDirs map[string]string
-}
-
-// AddBundleDirsRequest adds bundle directories that for the gofer to serve.
-func (api *api) AddBundleDirs(req *AddBundleDirsRequest, _ *struct{}) error {
- log.Debugf("fsgofer.AddBundleDirs")
- for cid, bd := range req.BundleDirs {
- if _, ok := api.bundleDirs[cid]; ok {
- return fmt.Errorf("fsgofer already has a bundleDir for container %q", cid)
- }
- api.bundleDirs[cid] = bd
- }
- return nil
-}
-
-// ServeDirectoryRequest is the URPC argument to ServeDirectory.
-type ServeDirectoryRequest struct {
- // Dir is the absolute path to a directory to be served to the sentry.
- Dir string
-
- // IsReadOnly specifies whether the directory should be served in
- // read-only mode.
- IsReadOnly bool
-
- // CID is the container ID of the container that needs to serve a
- // directory.
- CID string
-
- // FilePayload contains the socket over which the sentry will request
- // files from Dir.
- urpc.FilePayload
-}
-
-// ServeDirectory begins serving a directory via a file descriptor for the
-// sentry. Directories must be added via AddBundleDirsRequest before
-// ServeDirectory is called.
-func (api *api) ServeDirectory(req *ServeDirectoryRequest, _ *struct{}) error {
- log.Debugf("fsgofer.ServeDirectory: %+v", req)
-
- if req.Dir == "" {
- return fmt.Errorf("ServeDirectory should receive a directory argument, but was empty")
- }
- if req.CID == "" {
- return fmt.Errorf("ServeDirectory should receive a CID argument, but was empty")
- }
- // Prevent CIDs containing ".." from confusing the sentry when creating
- // /containers/<cid> directory.
- // TODO: Once we have multiple independant roots, this
- // check won't be necessary.
- if filepath.Clean(req.CID) != req.CID {
- return fmt.Errorf("container ID shouldn't contain directory traversals such as \"..\": %q", req.CID)
- }
- if nFiles := len(req.FilePayload.Files); nFiles != 1 {
- return fmt.Errorf("ServeDirectory should receive 1 file descriptor, but got %d", nFiles)
- }
-
- bd, ok := api.bundleDirs[req.CID]
- if !ok {
- // If there's no entry in bundleDirs for the container ID, this
- // is the root container.
- bd = api.rootBundleDir
- }
-
- // Relative paths are served relative to the bundle directory.
- absDir := req.Dir
- if !filepath.IsAbs(absDir) {
- absDir = filepath.Join(bd, req.Dir)
- }
-
- // Create the attach point and start serving.
- at := NewAttachPoint(absDir, Config{
- ROMount: req.IsReadOnly,
- LazyOpenForWrite: true,
- })
- api.serve(at, req.FilePayload.Files[0])
-
- return nil
-}
-
-// serve begins serving a directory via a file descriptor.
-func (api *api) serve(at p9.Attacher, ioFile *os.File) {
- api.p9wg.Add(1)
- go func() {
- socket, err := unet.NewSocket(int(ioFile.Fd()))
- if err != nil {
- panic(fmt.Sprintf("err creating server on FD %d: %v", ioFile.Fd(), err))
- }
- s := p9.NewServer(at)
- if err := s.Handle(socket); err != nil {
- panic(fmt.Sprintf("P9 server returned error. Gofer is shutting down. FD: %d, err: %v", ioFile.Fd(), err))
- }
- api.p9wg.Done()
- }()
-}