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
This commit is contained in:
Fabricio Voznika 2018-06-04 11:51:27 -07:00 committed by Shentubot
parent a0e2126be4
commit 55a37ceef1
3 changed files with 90 additions and 2 deletions

View File

@ -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",
],
)

View File

@ -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
}

View File

@ -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)
}
}