From 55a37ceef1e33cc72236db6e95f159963ddf40bd Mon Sep 17 00:00:00 2001 From: Fabricio Voznika Date: Mon, 4 Jun 2018 11:51:27 -0700 Subject: [PATCH] Fix leaky FD 9P socket was being created without CLOEXEC and was being inherited by the children. This would prevent the gofer from detecting that the sandbox had exited, because the socket would not be closed. PiperOrigin-RevId: 199168959 Change-Id: I3ee1a07cbe7331b0aeb1cf2b697e728ce24f85a7 --- runsc/sandbox/BUILD | 16 +++++++- runsc/sandbox/sandbox.go | 2 +- runsc/sandbox/sandbox_test.go | 74 +++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 runsc/sandbox/sandbox_test.go diff --git a/runsc/sandbox/BUILD b/runsc/sandbox/BUILD index e89b19552..a961c3cc7 100644 --- a/runsc/sandbox/BUILD +++ b/runsc/sandbox/BUILD @@ -1,6 +1,6 @@ package(licenses = ["notice"]) # Apache 2.0 -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "sandbox", @@ -28,3 +28,17 @@ go_library( "@org_golang_x_sys//unix:go_default_library", ], ) + +go_test( + name = "sandbox_test", + size = "small", + srcs = ["sandbox_test.go"], + data = [ + "//runsc", + ], + embed = [":sandbox"], + deps = [ + "//pkg/log", + "//runsc/test/testutil", + ], +) diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go index a9486cfdc..91c44c996 100644 --- a/runsc/sandbox/sandbox.go +++ b/runsc/sandbox/sandbox.go @@ -195,7 +195,7 @@ func (s *Sandbox) createGoferProcess(spec *specs.Spec, conf *boot.Config, bundle goferEnds := make([]*os.File, 0, mountCount) for i := 0; i < mountCount; i++ { // Create socket that connects the sandbox and gofer. - fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) + fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) if err != nil { return nil, err } diff --git a/runsc/sandbox/sandbox_test.go b/runsc/sandbox/sandbox_test.go new file mode 100644 index 000000000..e25290d5e --- /dev/null +++ b/runsc/sandbox/sandbox_test.go @@ -0,0 +1,74 @@ +// 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 sandbox + +import ( + "os" + "testing" + + "gvisor.googlesource.com/gvisor/pkg/log" + "gvisor.googlesource.com/gvisor/runsc/test/testutil" +) + +func init() { + log.SetLevel(log.Debug) + if err := testutil.ConfigureExePath(); err != nil { + panic(err.Error()) + } +} + +func TestGoferExits(t *testing.T) { + spec := testutil.NewSpecWithArgs("/bin/sleep", "10000") + rootDir, bundleDir, conf, err := testutil.SetupContainer(spec) + if err != nil { + t.Fatalf("error setting up container: %v", err) + } + defer os.RemoveAll(rootDir) + defer os.RemoveAll(bundleDir) + + // Create, start and wait for the container. + s, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "") + if err != nil { + t.Fatalf("error creating container: %v", err) + } + defer s.Destroy() + if err := s.Start("123", spec, conf); err != nil { + t.Fatalf("error starting container: %v", err) + } + + sandboxProc, err := os.FindProcess(s.Pid) + if err != nil { + t.Fatalf("error finding sandbox process: %v", err) + } + gofer, err := os.FindProcess(s.GoferPid) + if err != nil { + t.Fatalf("error finding sandbox process: %v", err) + } + + // Kill sandbox and expect gofer to exit on its own. + if err := sandboxProc.Kill(); err != nil { + t.Fatalf("error killing sandbox process: %v", err) + } + if _, err := sandboxProc.Wait(); err != nil { + t.Fatalf("error waiting for sandbox process: %v", err) + } + + if _, err := gofer.Wait(); err != nil { + t.Fatalf("error waiting for gofer process: %v", err) + } + if s.IsRunning() { + t.Errorf("Sandbox shouldn't be running, sandbox: %+v", s) + } +}