diff --git a/lib/bpf/bpf.go b/lib/bpf/bpf.go index 4b865e0f3d8..144c8c1ad1b 100644 --- a/lib/bpf/bpf.go +++ b/lib/bpf/bpf.go @@ -124,23 +124,23 @@ func New(config *Config) (BPF, error) { start := time.Now() log.Debugf("Starting enhanced session recording.") - // Compile and start BPF programs. - s.exec, err = startExec(closeContext, config.CommandBufferSize) + // Compile and start BPF programs if they are enabled (buffer size given). + s.exec, err = startExec(closeContext, *config.CommandBufferSize) if err != nil { return nil, trace.Wrap(err) } - s.open, err = startOpen(closeContext, config.DiskBufferSize) + s.open, err = startOpen(closeContext, *config.DiskBufferSize) if err != nil { return nil, trace.Wrap(err) } - s.conn, err = startConn(closeContext, config.NetworkBufferSize) + s.conn, err = startConn(closeContext, *config.NetworkBufferSize) if err != nil { return nil, trace.Wrap(err) } log.Debugf("Started enhanced session recording with buffer sizes (command=%v, "+ "disk=%v, network=%v) and cgroup mount path: %v. Took %v.", - s.CommandBufferSize, s.DiskBufferSize, s.NetworkBufferSize, s.CgroupPath, + *s.CommandBufferSize, *s.DiskBufferSize, *s.NetworkBufferSize, s.CgroupPath, time.Since(start)) // Start pulling events off the perf buffers and emitting them to the diff --git a/lib/bpf/command.go b/lib/bpf/command.go index 0f096d89e85..69929fc7027 100644 --- a/lib/bpf/command.go +++ b/lib/bpf/command.go @@ -89,6 +89,11 @@ func startExec(closeContext context.Context, pageCount int) (*exec, error) { closeContext: closeContext, } + // If the page count is zero, don't start any BPF module. + if pageCount == 0 { + return e, nil + } + // Compile the BPF program. e.module = bcc.NewModule(execveSource, []string{}) if e.module == nil { diff --git a/lib/bpf/common.go b/lib/bpf/common.go index 0c14a62a510..9dd6e3e1d33 100644 --- a/lib/bpf/common.go +++ b/lib/bpf/common.go @@ -85,13 +85,13 @@ type Config struct { Enabled bool // CommandBufferSize is the size of the perf buffer for command events. - CommandBufferSize int + CommandBufferSize *int // DiskBufferSize is the size of the perf buffer for disk events. - DiskBufferSize int + DiskBufferSize *int // NetworkBufferSize is the size of the perf buffer for network events. - NetworkBufferSize int + NetworkBufferSize *int // CgroupPath is where the cgroupv2 hierarchy is mounted. CgroupPath string @@ -99,14 +99,17 @@ type Config struct { // CheckAndSetDefaults checks BPF configuration. func (c *Config) CheckAndSetDefaults() error { - if c.CommandBufferSize == 0 { - c.CommandBufferSize = defaults.PerfBufferPageCount + var perfBufferPageCount = defaults.PerfBufferPageCount + var openPerfBufferPageCount = defaults.OpenPerfBufferPageCount + + if c.CommandBufferSize == nil { + c.CommandBufferSize = &perfBufferPageCount } - if c.DiskBufferSize == 0 { - c.DiskBufferSize = defaults.OpenPerfBufferPageCount + if c.DiskBufferSize == nil { + c.DiskBufferSize = &openPerfBufferPageCount } - if c.NetworkBufferSize == 0 { - c.NetworkBufferSize = defaults.PerfBufferPageCount + if c.NetworkBufferSize == nil { + c.NetworkBufferSize = &perfBufferPageCount } if c.CgroupPath == "" { c.CgroupPath = defaults.CgroupPath diff --git a/lib/bpf/common_test.go b/lib/bpf/common_test.go new file mode 100644 index 00000000000..083545a5c5c --- /dev/null +++ b/lib/bpf/common_test.go @@ -0,0 +1,87 @@ +/* +Copyright 2019 Gravitational, 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 bpf + +import ( + "fmt" + + "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/utils" + + "gopkg.in/check.v1" +) + +type CommonSuite struct{} + +var _ = fmt.Printf +var _ = check.Suite(&CommonSuite{}) + +func (s *CommonSuite) SetUpSuite(c *check.C) { + utils.InitLoggerForTests() +} +func (s *CommonSuite) TearDownSuite(c *check.C) {} +func (s *CommonSuite) SetUpTest(c *check.C) {} +func (s *CommonSuite) TearDownTest(c *check.C) {} + +// TestCheckAndSetDefaults makes sure defaults are set when the user does not +// provide values for the page sizes and hard coded values (like zero or a +// specific page size) are respected when given. +func (s *CommonSuite) TestCheckAndSetDefaults(c *check.C) { + var perfBufferPageCount = defaults.PerfBufferPageCount + var openPerfBufferPageCount = defaults.OpenPerfBufferPageCount + var zeroPageCount = 0 + + var tests = []struct { + inConfig *Config + outConfig *Config + }{ + // Empty values get defaults. + { + inConfig: &Config{ + CommandBufferSize: nil, + DiskBufferSize: nil, + NetworkBufferSize: nil, + }, + outConfig: &Config{ + CommandBufferSize: &perfBufferPageCount, + DiskBufferSize: &openPerfBufferPageCount, + NetworkBufferSize: &perfBufferPageCount, + }, + }, + // Values are not wiped out with defaults. + { + inConfig: &Config{ + CommandBufferSize: &zeroPageCount, + DiskBufferSize: &zeroPageCount, + NetworkBufferSize: &perfBufferPageCount, + }, + outConfig: &Config{ + CommandBufferSize: &zeroPageCount, + DiskBufferSize: &zeroPageCount, + NetworkBufferSize: &perfBufferPageCount, + }, + }, + } + + for _, tt := range tests { + err := tt.inConfig.CheckAndSetDefaults() + c.Assert(err, check.IsNil) + c.Assert(*tt.inConfig.CommandBufferSize, check.Equals, *tt.outConfig.CommandBufferSize) + c.Assert(*tt.inConfig.DiskBufferSize, check.Equals, *tt.outConfig.DiskBufferSize) + c.Assert(*tt.inConfig.NetworkBufferSize, check.Equals, *tt.outConfig.NetworkBufferSize) + } +} diff --git a/lib/bpf/disk.go b/lib/bpf/disk.go index 93a75758cfd..04701c0cca1 100644 --- a/lib/bpf/disk.go +++ b/lib/bpf/disk.go @@ -86,6 +86,11 @@ func startOpen(closeContext context.Context, pageCount int) (*open, error) { closeContext: closeContext, } + // If the page count is zero, don't start any BPF module. + if pageCount == 0 { + return e, nil + } + // Compile the BPF program. e.module = bcc.NewModule(openSource, []string{}) if e.module == nil { diff --git a/lib/bpf/network.go b/lib/bpf/network.go index 7e8c1487b73..c1fdf4f2fd6 100644 --- a/lib/bpf/network.go +++ b/lib/bpf/network.go @@ -118,6 +118,11 @@ func startConn(closeContext context.Context, pageCount int) (*conn, error) { closeContext: closeContext, } + // If the page count is zero, don't start any BPF module. + if pageCount == 0 { + return e, nil + } + e.module = bcc.NewModule(connSource, []string{}) if e.module == nil { return nil, trace.BadParameter("failed to load libbcc") diff --git a/lib/config/fileconf.go b/lib/config/fileconf.go index edd19d00f9c..3c94ccc788e 100644 --- a/lib/config/fileconf.go +++ b/lib/config/fileconf.go @@ -725,13 +725,13 @@ type BPF struct { Enabled string `yaml:"enabled"` // CommandBufferSize is the size of the perf buffer for command events. - CommandBufferSize int `yaml:"command_buffer_size"` + CommandBufferSize *int `yaml:"command_buffer_size,omitempty"` // DiskBufferSize is the size of the perf buffer for disk events. - DiskBufferSize int `yaml:"disk_buffer_size"` + DiskBufferSize *int `yaml:"disk_buffer_size,omitempty"` // NetworkBufferSize is the size of the perf buffer for network events. - NetworkBufferSize int `yaml:"network_buffer_size"` + NetworkBufferSize *int `yaml:"network_buffer_size,omitempty"` // CgroupPath controls where cgroupv2 hierarchy is mounted. CgroupPath string `yaml:"cgroup_path"`