Merge pull request #1141 from ijc/rootfsPropagation

containerd-shim: Do not remount root MS_SLAVE
This commit is contained in:
Phil Estes 2017-07-21 16:18:41 -04:00 committed by GitHub
commit a2df6d1adc
7 changed files with 56 additions and 16 deletions

View File

@ -67,9 +67,6 @@ func main() {
if err != nil { if err != nil {
return err return err
} }
if err := setupRoot(); err != nil {
return err
}
path, err := os.Getwd() path, err := os.Getwd()
if err != nil { if err != nil {
return err return err

View File

@ -10,7 +10,6 @@ import (
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"golang.org/x/net/context" "golang.org/x/net/context"
"golang.org/x/sys/unix"
"github.com/containerd/containerd/reaper" "github.com/containerd/containerd/reaper"
"github.com/containerd/containerd/sys" "github.com/containerd/containerd/sys"
@ -33,11 +32,6 @@ func setupSignals() (chan os.Signal, error) {
return signals, nil return signals, nil
} }
// setupRoot sets up the root as the shim is started in its own mount namespace
func setupRoot() error {
return unix.Mount("", "/", "", unix.MS_SLAVE|unix.MS_REC, "")
}
func newServer() *grpc.Server { func newServer() *grpc.Server {
return grpc.NewServer(grpc.Creds(NewUnixSocketCredentils(0, 0))) return grpc.NewServer(grpc.Creds(NewUnixSocketCredentils(0, 0)))
} }

View File

@ -23,11 +23,6 @@ func setupSignals() (chan os.Signal, error) {
return signals, nil return signals, nil
} }
// setupRoot is a no op except on Linux
func setupRoot() error {
return nil
}
func newServer() *grpc.Server { func newServer() *grpc.Server {
return grpc.NewServer() return grpc.NewServer()
} }

View File

@ -50,9 +50,12 @@ type initProcess struct {
closers []io.Closer closers []io.Closer
stdin io.Closer stdin io.Closer
stdio stdio stdio stdio
rootfs string
} }
func newInitProcess(context context.Context, path, namespace string, r *shimapi.CreateTaskRequest) (*initProcess, error) { func newInitProcess(context context.Context, path, namespace string, r *shimapi.CreateTaskRequest) (*initProcess, error) {
var success bool
if err := identifiers.Validate(r.ID); err != nil { if err := identifiers.Validate(r.ID); err != nil {
return nil, errors.Wrapf(err, "invalid task id") return nil, errors.Wrapf(err, "invalid task id")
} }
@ -64,13 +67,26 @@ func newInitProcess(context context.Context, path, namespace string, r *shimapi.
} }
options = *v.(*runcopts.CreateOptions) options = *v.(*runcopts.CreateOptions)
} }
rootfs := filepath.Join(path, "rootfs")
// count the number of successful mounts so we can undo
// what was actually done rather than what should have been
// done.
defer func() {
if success {
return
}
if err2 := mount.UnmountAll(rootfs, 0); err2 != nil {
log.G(context).WithError(err2).Warn("Failed to cleanup rootfs mount")
}
}()
for _, rm := range r.Rootfs { for _, rm := range r.Rootfs {
m := &mount.Mount{ m := &mount.Mount{
Type: rm.Type, Type: rm.Type,
Source: rm.Source, Source: rm.Source,
Options: rm.Options, Options: rm.Options,
} }
if err := m.Mount(filepath.Join(path, "rootfs")); err != nil { if err := m.Mount(rootfs); err != nil {
return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m) return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m)
} }
} }
@ -91,6 +107,7 @@ func newInitProcess(context context.Context, path, namespace string, r *shimapi.
stderr: r.Stderr, stderr: r.Stderr,
terminal: r.Terminal, terminal: r.Terminal,
}, },
rootfs: rootfs,
} }
var ( var (
err error err error
@ -170,6 +187,7 @@ func newInitProcess(context context.Context, path, namespace string, r *shimapi.
return nil, errors.Wrap(err, "failed to retrieve OCI runtime container pid") return nil, errors.Wrap(err, "failed to retrieve OCI runtime container pid")
} }
p.pid = pid p.pid = pid
success = true
return p, nil return p, nil
} }
@ -229,7 +247,16 @@ func (p *initProcess) Delete(context context.Context) error {
} }
p.io.Close() p.io.Close()
} }
return p.runtimeError(err, "OCI runtime delete failed") err = p.runtimeError(err, "OCI runtime delete failed")
if err2 := mount.UnmountAll(p.rootfs, 0); err2 != nil {
log.G(context).WithError(err2).Warn("Failed to cleanup rootfs mount")
if err == nil {
err = errors.Wrap(err2, "Failed rootfs umount")
}
}
return err
} }
func (p *initProcess) Resize(ws console.WinSize) error { func (p *initProcess) Resize(ws console.WinSize) error {

View File

@ -15,6 +15,25 @@ func Unmount(mount string, flags int) error {
return unix.Unmount(mount, flags) return unix.Unmount(mount, flags)
} }
// UnmountAll repeatedly unmounts the given mount point until there
// are no mounts remaining (EINVAL is returned by mount), which is
// useful for undoing a stack of mounts on the same mount point.
func UnmountAll(mount string, flags int) error {
for {
if err := Unmount(mount, flags); err != nil {
// EINVAL is returned if the target is not a
// mount point, indicating that we are
// done. It can also indicate a few other
// things (such as invalid flags) which we
// unfortunately end up squelching here too.
if err == unix.EINVAL {
return nil
}
return err
}
}
}
// parseMountOptions takes fstab style mount options and parses them for // parseMountOptions takes fstab style mount options and parses them for
// use with a standard mount() syscall // use with a standard mount() syscall
func parseMountOptions(options []string) (int, string) { func parseMountOptions(options []string) (int, string) {

View File

@ -15,3 +15,7 @@ func (m *Mount) Mount(target string) error {
func Unmount(mount string, flags int) error { func Unmount(mount string, flags int) error {
return ErrNotImplementOnUnix return ErrNotImplementOnUnix
} }
func UnmountAll(mount string, flags int) error {
return ErrNotImplementOnUnix
}

View File

@ -13,3 +13,7 @@ func (m *Mount) Mount(target string) error {
func Unmount(mount string, flags int) error { func Unmount(mount string, flags int) error {
return ErrNotImplementOnWindows return ErrNotImplementOnWindows
} }
func UnmountAll(mount string, flags int) error {
return ErrNotImplementOnWindows
}