Add support to disable BPF programs.

If the page size for an enhanced event is 0, then don't attempt to load
that BPF program. This is helpful for BPF programs that generate massive
amounts of events (like disk events).
This commit is contained in:
Russell Jones 2020-01-13 16:20:46 -08:00 committed by Russell Jones
parent 35127f797a
commit 995d9ffe25
7 changed files with 122 additions and 17 deletions

View file

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

View file

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

View file

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

87
lib/bpf/common_test.go Normal file
View file

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

View file

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

View file

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

View file

@ -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"`