Automated rollback of changelist 501671432

PiperOrigin-RevId: 504061302
This commit is contained in:
Fabricio Voznika
2023-01-23 13:06:50 -08:00
committed by gVisor bot
parent f8375fac10
commit cf52b8a4a2
4 changed files with 82 additions and 11 deletions
-5
View File
@@ -144,11 +144,6 @@ const (
CgroupsWriteControlFiles = "Cgroups.WriteControlFiles"
)
// ControlSocketAddr generates an abstract unix socket name for the given ID.
func ControlSocketAddr(id string) string {
return fmt.Sprintf("\x00runsc-sandbox.%s", id)
}
// controller holds the control server, and is used for communication into the
// sandbox.
type controller struct {
+1 -1
View File
@@ -104,7 +104,7 @@ func startGofer(root string) (int, func(), error) {
}
func createLoader(spec *specs.Spec) (*Loader, func(), error) {
fd, err := server.CreateSocket(ControlSocketAddr(fmt.Sprintf("%010d", rand.Int())[:10]))
fd, err := server.CreateSocket(fmt.Sprintf("\x00loader-test.%010d", rand.Int())[:10])
if err != nil {
return nil, nil, err
}
+41
View File
@@ -24,6 +24,7 @@ import (
"path"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"testing"
@@ -2683,3 +2684,43 @@ func TestSaveSystemdCgroup(t *testing.T) {
t.Errorf("CompatCgroup not properly saved: want %v, got %v", cont.CompatCgroup, loadCont.CompatCgroup)
}
}
// TestSandboxCommunicationUnshare checks that communication with sandboxes do
// not require being in the same network namespace. This is required to allow
// Kubernetes daemonsets/containers to communicate with sandboxes without the
// need to join the host network namespaces.
func TestSandboxCommunicationUnshare(t *testing.T) {
spec, conf := sleepSpecConf(t)
_, bundleDir, cleanup, err := testutil.SetupContainer(spec, conf)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
defer cleanup()
args := Args{
ID: testutil.RandomContainerID(),
Spec: spec,
BundleDir: bundleDir,
}
cont, err := New(conf, args)
if err != nil {
t.Fatalf("Creating container: %v", err)
}
defer cont.Destroy()
if err := cont.Start(conf); err != nil {
t.Fatalf("starting container: %v", err)
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if err := unix.Unshare(unix.CLONE_NEWNET); err != nil {
t.Fatalf("unix.Unshare(): %v", err)
}
// Send a simple command to test that the sandbox can be reached.
if err := cont.SignalContainer(0, true); err != nil {
t.Errorf("SignalContainer(): %v", err)
}
}
+40 -5
View File
@@ -24,6 +24,7 @@ import (
"math"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"syscall"
@@ -65,6 +66,30 @@ const (
namespaceAnnotation = "io.kubernetes.cri.sandbox-namespace"
)
// createControlSocket finds a location and creates the socket used to
// communicate with the sandbox.
func createControlSocket(rootDir, id string) (string, int, error) {
name := fmt.Sprintf("runsc-%s.sock", id)
// Only use absolute paths to guarantee resolution from anywhere.
var paths []string
for _, dir := range []string{rootDir, "/var/run", "/run", "/tmp"} {
paths = append(paths, filepath.Join(dir, name))
}
// If nothing else worked, use the abstract namespace.
paths = append(paths, fmt.Sprintf("\x00runsc-sandbox.%s", id))
for _, path := range paths {
log.Debugf("Attempting to create socket file %q", path)
fd, err := server.CreateSocket(path)
if err == nil {
log.Debugf("Using socket file %q", path)
return path, fd, nil
}
}
return "", -1, fmt.Errorf("unable to find location to write socket file")
}
// pid is an atomic type that implements JSON marshal/unmarshal interfaces.
type pid struct {
val atomicbitops.Int64
@@ -144,6 +169,9 @@ type Sandbox struct {
// created.
MetricServerAddress string `json:"metricServerAddress"`
// ControlAddress is the uRPC address used to connect to the sandbox.
ControlAddress string `json:"control_address"`
// child is set if a sandbox process is a child of the current process.
//
// This field isn't saved to json, because only a creator of sandbox
@@ -225,6 +253,7 @@ func New(conf *config.Config, args *Args) (*Sandbox, error) {
s.PodName = args.Spec.Annotations[podNameAnnotation]
s.Namespace = args.Spec.Annotations[namespaceAnnotation]
}
// The Cleanup object cleans up partially created sandboxes when an error
// occurs. Any errors occurring during cleanup itself are ignored.
c := cleanup.Make(func() {
@@ -514,7 +543,7 @@ func (s *Sandbox) Event(cid string) (*boot.EventOut, error) {
func (s *Sandbox) sandboxConnect() (*urpc.Client, error) {
log.Debugf("Connecting to sandbox %q", s.ID)
conn, err := client.ConnectTo(boot.ControlSocketAddr(s.ID))
conn, err := client.ConnectTo(s.ControlAddress)
if err != nil {
return nil, s.connError(err)
}
@@ -622,12 +651,12 @@ func (s *Sandbox) createSandboxProcess(conf *config.Config, args *Args, startSyn
}
// Create a socket for the control server and donate it to the sandbox.
addr := boot.ControlSocketAddr(s.ID)
sockFD, err := server.CreateSocket(addr)
log.Infof("Creating sandbox process with addr: %s", addr[1:]) // skip "\00".
controlAddress, sockFD, err := createControlSocket(conf.RootDir, s.ID)
if err != nil {
return fmt.Errorf("creating control server socket for sandbox %q: %v", s.ID, err)
return fmt.Errorf("creating control socket %q: %v", s.ControlAddress, err)
}
log.Infof("Control socket: %q", s.ControlAddress)
s.ControlAddress = controlAddress
donations.DonateAndClose("controller-fd", os.NewFile(uintptr(sockFD), "control_server_socket"))
specFile, err := specutils.OpenSpec(args.BundleDir)
@@ -1000,6 +1029,12 @@ func (s *Sandbox) IsRootContainer(cid string) bool {
// is idempotent.
func (s *Sandbox) destroy() error {
log.Debugf("Destroying sandbox %q", s.ID)
// Only delete the control file if it exists and is not an abstract UDS.
if len(s.ControlAddress) > 0 && s.ControlAddress[0] != 0 {
if err := os.Remove(s.ControlAddress); err != nil {
log.Warningf("failed to delete control socket file %q: %v", s.ControlAddress, err)
}
}
pid := s.Pid.load()
if pid != 0 {
log.Debugf("Killing sandbox %q", s.ID)