diff --git a/runsc/boot/BUILD b/runsc/boot/BUILD index 998ad5cf7..5507ce0b4 100644 --- a/runsc/boot/BUILD +++ b/runsc/boot/BUILD @@ -48,7 +48,6 @@ go_library( "//pkg/sentry/arch", "//pkg/sentry/arch:registers_go_proto", "//pkg/sentry/control", - "//pkg/sentry/control:control_go_proto", "//pkg/sentry/devices/memdev", "//pkg/sentry/devices/ttydev", "//pkg/sentry/devices/tundev", diff --git a/runsc/boot/controller.go b/runsc/boot/controller.go index bd69b2f29..3786aa7cf 100644 --- a/runsc/boot/controller.go +++ b/runsc/boot/controller.go @@ -26,7 +26,6 @@ import ( "gvisor.dev/gvisor/pkg/fd" "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/sentry/control" - controlpb "gvisor.dev/gvisor/pkg/sentry/control/control_go_proto" "gvisor.dev/gvisor/pkg/sentry/kernel" "gvisor.dev/gvisor/pkg/sentry/seccheck" "gvisor.dev/gvisor/pkg/sentry/socket/netstack" @@ -123,11 +122,6 @@ const ( LifecycleResume = "Lifecycle.Resume" ) -// Filesystem related commands (see fs.go for more details). -const ( - FsCat = "Fs.Cat" -) - // Usage related commands (see usage.go for more details). const ( UsageCollect = "Usage.Collect" @@ -135,11 +129,6 @@ const ( UsageReduce = "Usage.Reduce" ) -// Events related commands (see events.go for more details). -const ( - EventsAttachDebugEmitter = "Events.AttachDebugEmitter" -) - // ControlSocketAddr generates an abstract unix socket name for the given ID. func ControlSocketAddr(id string) string { return fmt.Sprintf("\x00runsc-sandbox.%s", id) @@ -158,54 +147,33 @@ type controller struct { // newController creates a new controller. The caller must call // controller.srv.StartServing() to start the controller. func newController(fd int, l *Loader) (*controller, error) { - ctrl := &controller{} - var err error - ctrl.srv, err = server.CreateFromFD(fd) + srv, err := server.CreateFromFD(fd) if err != nil { return nil, err } - ctrl.manager = &containerManager{ - startChan: make(chan struct{}), - startResultChan: make(chan error), - l: l, + ctrl := &controller{ + manager: &containerManager{ + startChan: make(chan struct{}), + startResultChan: make(chan error), + l: l, + }, + srv: srv, } ctrl.srv.Register(ctrl.manager) + ctrl.srv.Register(&control.Lifecycle{Kernel: l.k}) + ctrl.srv.Register(&control.Logging{}) + ctrl.srv.Register(&control.Proc{Kernel: l.k}) + ctrl.srv.Register(&control.State{Kernel: l.k}) + ctrl.srv.Register(&control.Usage{Kernel: l.k}) + ctrl.srv.Register(&debug{}) if eps, ok := l.k.RootNetworkNamespace().Stack().(*netstack.Stack); ok { - net := &Network{ - Stack: eps.Stack, - } - ctrl.srv.Register(net) + ctrl.srv.Register(&Network{Stack: eps.Stack}) } - - if l.root.conf.Controls.Controls != nil { - for _, c := range l.root.conf.Controls.Controls.AllowedControls { - switch c { - case controlpb.ControlConfig_EVENTS: - ctrl.srv.Register(&control.Events{}) - case controlpb.ControlConfig_FS: - ctrl.srv.Register(&control.Fs{Kernel: l.k}) - case controlpb.ControlConfig_LIFECYCLE: - ctrl.srv.Register(&control.Lifecycle{Kernel: l.k}) - case controlpb.ControlConfig_LOGGING: - ctrl.srv.Register(&control.Logging{}) - case controlpb.ControlConfig_PROFILE: - if l.root.conf.ProfileEnable { - ctrl.srv.Register(control.NewProfile(l.k)) - } - case controlpb.ControlConfig_USAGE: - ctrl.srv.Register(&control.Usage{Kernel: l.k}) - case controlpb.ControlConfig_PROC: - ctrl.srv.Register(&control.Proc{Kernel: l.k}) - case controlpb.ControlConfig_STATE: - ctrl.srv.Register(&control.State{Kernel: l.k}) - case controlpb.ControlConfig_DEBUG: - ctrl.srv.Register(&debug{}) - } - } + if l.root.conf.ProfileEnable { + ctrl.srv.Register(control.NewProfile(l.k)) } - return ctrl, nil } diff --git a/runsc/cmd/debug.go b/runsc/cmd/debug.go index b42b04776..983a56810 100644 --- a/runsc/cmd/debug.go +++ b/runsc/cmd/debug.go @@ -49,7 +49,6 @@ type Debug struct { delay time.Duration duration time.Duration ps bool - cat stringSlice } // Name implements subcommands.Command. @@ -83,7 +82,6 @@ func (d *Debug) SetFlags(f *flag.FlagSet) { f.StringVar(&d.logLevel, "log-level", "", "The log level to set: warning (0), info (1), or debug (2).") f.StringVar(&d.logPackets, "log-packets", "", "A boolean value to enable or disable packet logging: true or false.") f.BoolVar(&d.ps, "ps", false, "lists processes") - f.Var(&d.cat, "cat", "reads files and print to standard output") } // Execute implements subcommands.Command.Execute. @@ -379,11 +377,5 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) return subcommands.ExitFailure } - if d.cat != nil { - if err := c.Cat(d.cat, os.Stdout); err != nil { - return util.Errorf("Cat failed: %v", err) - } - } - return subcommands.ExitSuccess } diff --git a/runsc/cmd/events.go b/runsc/cmd/events.go index b5ac25306..652167595 100644 --- a/runsc/cmd/events.go +++ b/runsc/cmd/events.go @@ -34,10 +34,6 @@ type Events struct { intervalSec int // If true, events will print a single group of stats and exit. stats bool - // If true, events will dump all filtered events to stdout. - stream bool - // filters for streamed events. - filters stringSlice } // Name implements subcommands.Command.Name. @@ -67,8 +63,6 @@ OPTIONS: func (evs *Events) SetFlags(f *flag.FlagSet) { f.IntVar(&evs.intervalSec, "interval", 5, "set the stats collection interval, in seconds") f.BoolVar(&evs.stats, "stats", false, "display the container's stats then exit") - f.BoolVar(&evs.stream, "stream", false, "dump all filtered events to stdout") - f.Var(&evs.filters, "filters", "only display matching events") } // Execute implements subcommands.Command.Execute. @@ -86,15 +80,9 @@ func (evs *Events) Execute(_ context.Context, f *flag.FlagSet, args ...interface util.Fatalf("loading sandbox: %v", err) } - if evs.stream { - if err := c.Stream(evs.filters, os.Stdout); err != nil { - util.Fatalf("Stream failed: %v", err) - } - return subcommands.ExitSuccess - } - - // Repeatedly get stats from the container. - for { + // Repeatedly get stats from the container. Sleep a bit after every loop + // except the first one. + for dur := time.Duration(evs.intervalSec) * time.Second; true; time.Sleep(dur) { // Get the event and print it as JSON. ev, err := c.Event() if err != nil { @@ -102,29 +90,22 @@ func (evs *Events) Execute(_ context.Context, f *flag.FlagSet, args ...interface if evs.stats { return subcommands.ExitFailure } + continue } log.Debugf("Events: %+v", ev) - // err must be preserved because it is used below when breaking - // out of the loop. - b, err := json.Marshal(ev.Event) - if err != nil { - log.Warningf("Error while marshalling event %v: %v", ev.Event, err) - } else { - if _, err := os.Stdout.Write(b); err != nil { - util.Fatalf("Error writing to stdout: %v", err) - } - } - - // If we're only running once, break. If we're only running - // once and there was an error, the command failed. - if evs.stats { - if err != nil { + if err := json.NewEncoder(os.Stdout).Encode(ev.Event); err != nil { + log.Warningf("Error encoding event %+v: %v", ev.Event, err) + if evs.stats { return subcommands.ExitFailure } - return subcommands.ExitSuccess + continue } - time.Sleep(time.Duration(evs.intervalSec) * time.Second) + // Break if we're only running once. If we got this far it was a success. + if evs.stats { + return subcommands.ExitSuccess + } } + panic("should never get here") } diff --git a/runsc/config/BUILD b/runsc/config/BUILD index 004a98332..ab1905823 100644 --- a/runsc/config/BUILD +++ b/runsc/config/BUILD @@ -11,7 +11,6 @@ go_library( visibility = ["//:sandbox"], deps = [ "//pkg/refs", - "//pkg/sentry/control:control_go_proto", "//pkg/sentry/watchdog", "//runsc/flag", ], @@ -24,8 +23,5 @@ go_test( "config_test.go", ], library = ":config", - deps = [ - "//pkg/sentry/control:control_go_proto", - "//runsc/flag", - ], + deps = ["//runsc/flag"], ) diff --git a/runsc/config/config.go b/runsc/config/config.go index 08e9fad0e..6238f7017 100644 --- a/runsc/config/config.go +++ b/runsc/config/config.go @@ -19,10 +19,8 @@ package config import ( "fmt" - "strings" "gvisor.dev/gvisor/pkg/refs" - controlpb "gvisor.dev/gvisor/pkg/sentry/control/control_go_proto" "gvisor.dev/gvisor/pkg/sentry/watchdog" ) @@ -172,9 +170,6 @@ type Config struct { // for the duration of the container execution. TraceFile string `flag:"trace"` - // Controls defines the controls that may be enabled. - Controls controlConfig `flag:"controls"` - // RestoreFile is the path to the saved container image. RestoreFile string @@ -428,96 +423,6 @@ func (q QueueingDiscipline) String() string { panic(fmt.Sprintf("Invalid qdisc %d", q)) } -// controlConfig represents control endpoints. -type controlConfig struct { - Controls *controlpb.ControlConfig -} - -// Set implements flag.Value. -func (c *controlConfig) Set(v string) error { - controls := strings.Split(v, ",") - var controlList []controlpb.ControlConfig_Endpoint - for _, control := range controls { - switch control { - case "EVENTS": - controlList = append(controlList, controlpb.ControlConfig_EVENTS) - case "FS": - controlList = append(controlList, controlpb.ControlConfig_FS) - case "LIFECYCLE": - controlList = append(controlList, controlpb.ControlConfig_LIFECYCLE) - case "LOGGING": - controlList = append(controlList, controlpb.ControlConfig_LOGGING) - case "PROFILE": - controlList = append(controlList, controlpb.ControlConfig_PROFILE) - case "USAGE": - controlList = append(controlList, controlpb.ControlConfig_USAGE) - case "PROC": - controlList = append(controlList, controlpb.ControlConfig_PROC) - case "STATE": - controlList = append(controlList, controlpb.ControlConfig_STATE) - case "DEBUG": - controlList = append(controlList, controlpb.ControlConfig_DEBUG) - default: - return fmt.Errorf("invalid control %q", control) - } - } - c.Controls.AllowedControls = controlList - return nil -} - -// Get implements flag.Value. -func (c *controlConfig) Get() interface{} { - return *c -} - -// String implements flag.Value. -func (c *controlConfig) String() string { - v := "" - for _, control := range c.Controls.GetAllowedControls() { - if len(v) > 0 { - v += "," - } - switch control { - case controlpb.ControlConfig_EVENTS: - v += "EVENTS" - case controlpb.ControlConfig_FS: - v += "FS" - case controlpb.ControlConfig_LIFECYCLE: - v += "LIFECYCLE" - case controlpb.ControlConfig_LOGGING: - v += "LOGGING" - case controlpb.ControlConfig_PROFILE: - v += "PROFILE" - case controlpb.ControlConfig_USAGE: - v += "USAGE" - case controlpb.ControlConfig_PROC: - v += "PROC" - case controlpb.ControlConfig_STATE: - v += "STATE" - case controlpb.ControlConfig_DEBUG: - v += "DEBUG" - default: - panic(fmt.Sprintf("Invalid control %d", control)) - } - } - return v -} - -func defaultControlConfig() *controlConfig { - c := controlConfig{} - c.Controls = &controlpb.ControlConfig{} - c.Controls.AllowedControls = append(c.Controls.AllowedControls, controlpb.ControlConfig_EVENTS) - c.Controls.AllowedControls = append(c.Controls.AllowedControls, controlpb.ControlConfig_FS) - c.Controls.AllowedControls = append(c.Controls.AllowedControls, controlpb.ControlConfig_LIFECYCLE) - c.Controls.AllowedControls = append(c.Controls.AllowedControls, controlpb.ControlConfig_LOGGING) - c.Controls.AllowedControls = append(c.Controls.AllowedControls, controlpb.ControlConfig_PROFILE) - c.Controls.AllowedControls = append(c.Controls.AllowedControls, controlpb.ControlConfig_USAGE) - c.Controls.AllowedControls = append(c.Controls.AllowedControls, controlpb.ControlConfig_PROC) - c.Controls.AllowedControls = append(c.Controls.AllowedControls, controlpb.ControlConfig_STATE) - c.Controls.AllowedControls = append(c.Controls.AllowedControls, controlpb.ControlConfig_DEBUG) - return &c -} - func leakModePtr(v refs.LeakMode) *refs.LeakMode { return &v } diff --git a/runsc/config/config_test.go b/runsc/config/config_test.go index 2e34bb11b..ad705479a 100644 --- a/runsc/config/config_test.go +++ b/runsc/config/config_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - controlpb "gvisor.dev/gvisor/pkg/sentry/control/control_go_proto" "gvisor.dev/gvisor/runsc/flag" ) @@ -55,9 +54,6 @@ func TestFromFlags(t *testing.T) { if err := testFlags.Lookup("network").Value.Set("none"); err != nil { t.Errorf("Flag set: %v", err) } - if err := testFlags.Lookup("controls").Value.Set("EVENTS,FS"); err != nil { - t.Errorf("Flag set: %v", err) - } c, err := NewFromFlags(testFlags) if err != nil { @@ -75,12 +71,6 @@ func TestFromFlags(t *testing.T) { if want := NetworkNone; c.Network != want { t.Errorf("Network=%v, want: %v", c.Network, want) } - wants := []controlpb.ControlConfig_Endpoint{controlpb.ControlConfig_EVENTS, controlpb.ControlConfig_FS} - for i, want := range wants { - if c.Controls.Controls.AllowedControls[i] != want { - t.Errorf("Controls.Controls.AllowedControls[%d]=%v, want: %v", i, c.Controls.Controls.AllowedControls[i], want) - } - } } func TestToFlags(t *testing.T) { @@ -94,14 +84,9 @@ func TestToFlags(t *testing.T) { c.Debug = true c.NumNetworkChannels = 123 c.Network = NetworkNone - c.Controls = controlConfig{ - Controls: &controlpb.ControlConfig{ - AllowedControls: []controlpb.ControlConfig_Endpoint{controlpb.ControlConfig_EVENTS, controlpb.ControlConfig_FS}, - }, - } flags := c.ToFlags() - if len(flags) != 5 { + if len(flags) != 4 { t.Errorf("wrong number of flags set, want: 5, got: %d: %s", len(flags), flags) } t.Logf("Flags: %s", flags) @@ -115,7 +100,6 @@ func TestToFlags(t *testing.T) { "--debug": "true", "--num-network-channels": "123", "--network": "none", - "--controls": "EVENTS,FS", } { if got, ok := fm[name]; ok { if got != want { diff --git a/runsc/config/flags.go b/runsc/config/flags.go index 8d8e62bfa..15fe1ae77 100644 --- a/runsc/config/flags.go +++ b/runsc/config/flags.go @@ -70,7 +70,6 @@ func RegisterFlags(flagSet *flag.FlagSet) { flagSet.Var(leakModePtr(refs.NoLeakChecking), "ref-leak-mode", "sets reference leak check mode: disabled (default), log-names, log-traces.") flagSet.Bool("cpu-num-from-quota", false, "set cpu number to cpu quota (least integer greater or equal to quota value, but not less than 2)") flagSet.Bool("oci-seccomp", false, "Enables loading OCI seccomp filters inside the sandbox.") - flagSet.Var(defaultControlConfig(), "controls", "Sentry control endpoints.") flagSet.Bool("enable-core-tags", false, "enables core tagging. Requires host linux kernel >= 5.14.") flagSet.String("pod-init-config", "", "path to configuration file with additional steps to take during pod creation.") diff --git a/runsc/container/container.go b/runsc/container/container.go index 85b11080a..97e6c11da 100644 --- a/runsc/container/container.go +++ b/runsc/container/container.go @@ -672,18 +672,6 @@ func (c *Container) Resume() error { return c.saveLocked() } -// Cat prints out the content of the files. -func (c *Container) Cat(files []string, out *os.File) error { - log.Debugf("Cat in container, cid: %s, files: %+v", c.ID, files) - return c.Sandbox.Cat(c.ID, files, out) -} - -// Stream dumps all events to out. -func (c *Container) Stream(filters []string, out *os.File) error { - log.Debugf("Stream in container, cid: %s", c.ID) - return c.Sandbox.Stream(c.ID, filters, out) -} - // State returns the metadata of the container. func (c *Container) State() specs.State { return specs.State{ diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go index f897259f3..e509b06bb 100644 --- a/runsc/container/container_test.go +++ b/runsc/container/container_test.go @@ -2509,61 +2509,6 @@ func TestRlimitsExec(t *testing.T) { } } -// TestCat creates a file and checks that cat generates the expected output. -func TestCat(t *testing.T) { - f, err := ioutil.TempFile(testutil.TmpDir(), "test-case") - if err != nil { - t.Fatalf("ioutil.TempFile failed: %v", err) - } - defer os.RemoveAll(f.Name()) - - content := "test-cat" - if _, err := f.WriteString(content); err != nil { - t.Fatalf("f.WriteString(): %v", err) - } - f.Close() - - 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) - } - - r, w, err := os.Pipe() - if err != nil { - t.Fatalf("os.Create(): %v", err) - } - - if err := cont.Cat([]string{f.Name()}, w); err != nil { - t.Fatalf("error cat from container: %v", err) - } - - buf := make([]byte, 1024) - if _, err := r.Read(buf); err != nil { - t.Fatalf("Read out: %v", err) - } - if got, want := string(buf), content; !strings.Contains(got, want) { - t.Errorf("out got %s, want include %s", buf, want) - } -} - // TestUsage checks that usage generates the expected memory usage. func TestUsage(t *testing.T) { spec, conf := sleepSpecConf(t) @@ -2688,56 +2633,6 @@ func TestReduce(t *testing.T) { } } -// TestStream checks that Stream dumps expected events. -func TestStream(t *testing.T) { - spec, conf := sleepSpecConf(t) - conf.Strace = true - conf.StraceEvent = true - conf.StraceSyscalls = "" - - _, 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) - } - - r, w, err := os.Pipe() - if err != nil { - t.Fatalf("os.Create(): %v", err) - } - - // Spawn a new thread to Stream events as it blocks indefinitely. - go func() { - cont.Stream(nil, w) - }() - - buf := make([]byte, 1024) - if _, err := r.Read(buf); err != nil { - t.Fatalf("Read out: %v", err) - } - - // A syscall strace event includes "Strace". - if got, want := string(buf), "Strace"; !strings.Contains(got, want) { - t.Errorf("out got %s, want include %s", buf, want) - } -} - // TestProfile checks that profiling options generate profiles. func TestProfile(t *testing.T) { // Perform a non-trivial amount of work so we actually capture diff --git a/runsc/sandbox/BUILD b/runsc/sandbox/BUILD index 61a89b560..65d2b557f 100644 --- a/runsc/sandbox/BUILD +++ b/runsc/sandbox/BUILD @@ -19,7 +19,6 @@ go_library( "//pkg/control/client", "//pkg/control/server", "//pkg/coverage", - "//pkg/eventchannel", "//pkg/log", "//pkg/sentry/control", "//pkg/sentry/platform", @@ -27,7 +26,6 @@ go_library( "//pkg/sync", "//pkg/tcpip/header", "//pkg/tcpip/stack", - "//pkg/unet", "//pkg/urpc", "//runsc/boot", "//runsc/boot/procfs", diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go index 0016a852f..c27bd3f51 100644 --- a/runsc/sandbox/sandbox.go +++ b/runsc/sandbox/sandbox.go @@ -38,13 +38,11 @@ import ( "gvisor.dev/gvisor/pkg/control/client" "gvisor.dev/gvisor/pkg/control/server" "gvisor.dev/gvisor/pkg/coverage" - "gvisor.dev/gvisor/pkg/eventchannel" "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/sentry/control" "gvisor.dev/gvisor/pkg/sentry/platform" "gvisor.dev/gvisor/pkg/sentry/seccheck" "gvisor.dev/gvisor/pkg/sync" - "gvisor.dev/gvisor/pkg/unet" "gvisor.dev/gvisor/pkg/urpc" "gvisor.dev/gvisor/runsc/boot" "gvisor.dev/gvisor/runsc/boot/procfs" @@ -1121,24 +1119,6 @@ func (s *Sandbox) Resume(cid string) error { return nil } -// Cat sends the cat call for a container in the sandbox. -func (s *Sandbox) Cat(cid string, files []string, out *os.File) error { - log.Debugf("Cat sandbox %q", s.ID) - conn, err := s.sandboxConnect() - if err != nil { - return err - } - defer conn.Close() - - if err := conn.Call(boot.FsCat, &control.CatOpts{ - Files: files, - FilePayload: urpc.FilePayload{Files: []*os.File{out}}, - }, nil); err != nil { - return fmt.Errorf("Cat container %q: %v", cid, err) - } - return nil -} - // Usage sends the collect call for a container in the sandbox. func (s *Sandbox) Usage(Full bool) (control.MemoryUsage, error) { log.Debugf("Usage sandbox %q", s.ID) @@ -1192,37 +1172,6 @@ func (s *Sandbox) Reduce(wait bool) error { }, nil) } -// Stream sends the AttachDebugEmitter call for a container in the sandbox, and -// dumps filtered events to out. -func (s *Sandbox) Stream(cid string, filters []string, out *os.File) error { - log.Debugf("Stream sandbox %q", s.ID) - conn, err := s.sandboxConnect() - if err != nil { - return err - } - defer conn.Close() - - r, w, err := unet.SocketPair(false) - if err != nil { - return err - } - - wfd, err := w.Release() - if err != nil { - return fmt.Errorf("failed to release write socket FD: %v", err) - } - - if err := conn.Call(boot.EventsAttachDebugEmitter, &control.EventsOpts{ - FilePayload: urpc.FilePayload{Files: []*os.File{ - os.NewFile(uintptr(wfd), "event sink"), - }}, - }, nil); err != nil { - return fmt.Errorf("AttachDebugEmitter failed: %v", err) - } - - return eventchannel.ProcessAll(r, filters, out) -} - // IsRunning returns true if the sandbox or gofer process is running. func (s *Sandbox) IsRunning() bool { pid := s.Pid.load()