From bc9b979b9412ad5852872c1a9bee462f73d2455e Mon Sep 17 00:00:00 2001 From: Fabricio Voznika Date: Mon, 11 Mar 2019 11:46:18 -0700 Subject: Add profiling commands to runsc Example: runsc debug --root= \ --profile-heap=/tmp/heap.prof \ --profile-cpu=/tmp/cpu.prod --profile-delay=30 \ PiperOrigin-RevId: 237848456 Change-Id: Icff3f20c1b157a84d0922599eaea327320dad773 --- runsc/boot/config.go | 4 ++++ runsc/boot/controller.go | 8 ++++++++ runsc/boot/filter/config.go | 13 +++++++++++++ runsc/boot/filter/filter.go | 11 ++++++++--- runsc/boot/loader.go | 7 ++++--- 5 files changed, 37 insertions(+), 6 deletions(-) (limited to 'runsc/boot') diff --git a/runsc/boot/config.go b/runsc/boot/config.go index 400203c99..626fcabdd 100644 --- a/runsc/boot/config.go +++ b/runsc/boot/config.go @@ -202,6 +202,9 @@ type Config struct { // SIGUSR2(12) to troubleshoot hangs. -1 disables it. PanicSignal int + // ProfileEnable is set to prepare the sandbox to be profiled. + ProfileEnable bool + // TestOnlyAllowRunAsCurrentUserWithoutChroot should only be used in // tests. It allows runsc to start the sandbox process as the current // user, and without chrooting the sandbox process. This can be @@ -228,6 +231,7 @@ func (c *Config) ToFlags() []string { "--strace-log-size=" + strconv.Itoa(int(c.StraceLogSize)), "--watchdog-action=" + c.WatchdogAction.String(), "--panic-signal=" + strconv.Itoa(c.PanicSignal), + "--profile=" + strconv.FormatBool(c.ProfileEnable), } if c.TestOnlyAllowRunAsCurrentUserWithoutChroot { // Only include if set since it is never to be used by users. diff --git a/runsc/boot/controller.go b/runsc/boot/controller.go index 23d476f7f..a864be720 100644 --- a/runsc/boot/controller.go +++ b/runsc/boot/controller.go @@ -95,6 +95,11 @@ const ( // SandboxStacks collects sandbox stacks for debugging. SandboxStacks = "debug.Stacks" + + // Profiling related commands (see pprof.go for more details). + StartCPUProfile = "Profile.StartCPUProfile" + StopCPUProfile = "Profile.StopCPUProfile" + HeapProfile = "Profile.HeapProfile" ) // ControlSocketAddr generates an abstract unix socket name for the given ID. @@ -135,6 +140,9 @@ func newController(fd int, l *Loader) (*controller, error) { } srv.Register(&debug{}) + if l.conf.ProfileEnable { + srv.Register(&control.Profile{}) + } return &controller{ srv: srv, diff --git a/runsc/boot/filter/config.go b/runsc/boot/filter/config.go index bde749861..1ba5b7257 100644 --- a/runsc/boot/filter/config.go +++ b/runsc/boot/filter/config.go @@ -470,3 +470,16 @@ func controlServerFilters(fd int) seccomp.SyscallRules { }, } } + +// profileFilters returns extra syscalls made by runtime/pprof package. +func profileFilters() seccomp.SyscallRules { + return seccomp.SyscallRules{ + syscall.SYS_OPENAT: []seccomp.Rule{ + { + seccomp.AllowAny{}, + seccomp.AllowAny{}, + seccomp.AllowValue(syscall.O_RDONLY | syscall.O_LARGEFILE | syscall.O_CLOEXEC), + }, + }, + } +} diff --git a/runsc/boot/filter/filter.go b/runsc/boot/filter/filter.go index d69a6a2cc..fb197f9b1 100644 --- a/runsc/boot/filter/filter.go +++ b/runsc/boot/filter/filter.go @@ -29,9 +29,10 @@ import ( // Options are seccomp filter related options. type Options struct { - Platform platform.Platform - HostNetwork bool - ControllerFD int + Platform platform.Platform + HostNetwork bool + ProfileEnable bool + ControllerFD int } // Install installs seccomp filters for based on the given platform. @@ -47,6 +48,10 @@ func Install(opt Options) error { Report("host networking enabled: syscall filters less restrictive!") s.Merge(hostInetFilters()) } + if opt.ProfileEnable { + Report("profile enabled: syscall filters less restrictive!") + s.Merge(profileFilters()) + } switch p := opt.Platform.(type) { case *ptrace.PTrace: diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go index 42fe6f312..4c7e6abfc 100644 --- a/runsc/boot/loader.go +++ b/runsc/boot/loader.go @@ -445,9 +445,10 @@ func (l *Loader) run() error { filter.Report("syscall filter is DISABLED. Running in less secure mode.") } else { opts := filter.Options{ - Platform: l.k.Platform, - HostNetwork: l.conf.Network == NetworkHost, - ControllerFD: l.ctrl.srv.FD(), + Platform: l.k.Platform, + HostNetwork: l.conf.Network == NetworkHost, + ProfileEnable: l.conf.ProfileEnable, + ControllerFD: l.ctrl.srv.FD(), } if err := filter.Install(opts); err != nil { return fmt.Errorf("installing seccomp filters: %v", err) -- cgit v1.2.3