Skip to content

Commit

Permalink
Merge branch 'cilium:main' into pr/XelK/helm-gops
Browse files Browse the repository at this point in the history
  • Loading branch information
XelK authored Sep 30, 2024
2 parents 753a6f7 + 19ba896 commit 64e69f1
Show file tree
Hide file tree
Showing 7 changed files with 391 additions and 32 deletions.
2 changes: 1 addition & 1 deletion bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ PROCESS = bpf_execve_event.o bpf_execve_event_v53.o bpf_fork.o bpf_exit.o bpf_ge
bpf_loader.o \
bpf_cgroup.o \
bpf_enforcer.o bpf_multi_enforcer.o bpf_fmodret_enforcer.o \
bpf_map_test_p1.o bpf_map_test_p2.o
bpf_map_test_p1.o bpf_map_test_p2.o bpf_map_test_p3.o

CGROUP = bpf_cgroup_mkdir.o bpf_cgroup_rmdir.o bpf_cgroup_release.o
BPFTEST = bpf_lseek.o
Expand Down
22 changes: 22 additions & 0 deletions bpf/process/bpf_map_test_p3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright Authors of Cilium */

#include "vmlinux.h"
#include "api.h"
#include "bpf_tracing.h"
#include "bpf_helpers.h"
#include "compiler.h"

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1);
__type(key, int);
__type(value, unsigned long);
} m1 SEC(".maps");

__attribute__((section("kprobe/wake_up_new_task"), used)) int
BPF_KPROBE(p2)
{
map_lookup_elem(&m1, &(unsigned long){ 0 });
return 0;
}
18 changes: 14 additions & 4 deletions pkg/observer/observertesthelper/observer_test_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,22 @@ func GetDefaultObserverWithFile(tb testing.TB, ctx context.Context, file, lib st
return GetDefaultObserverWithWatchers(tb, ctx, b, opts...)
}

func GetDefaultSensorsWithBase(tb testing.TB, b *sensors.Sensor, file, lib string, opts ...TestOption) ([]*sensors.Sensor, error) {
opts = append(opts, WithConfig(file))
opts = append(opts, WithLib(lib))

return getDefaultSensors(tb, b, opts...)
}

func GetDefaultSensorsWithFile(tb testing.TB, file, lib string, opts ...TestOption) ([]*sensors.Sensor, error) {
opts = append(opts, WithConfig(file))
opts = append(opts, WithLib(lib))

b := base.GetInitialSensor()
return getDefaultSensors(tb, b, opts...)
}

func getDefaultSensors(tb testing.TB, initialSensor *sensors.Sensor, opts ...TestOption) ([]*sensors.Sensor, error) {
option.Config.BpfDir = bpf.MapPrefixPath()

testutils.CaptureLog(tb, logger.GetLogger().(*logrus.Logger))
Expand Down Expand Up @@ -327,13 +339,11 @@ func GetDefaultSensorsWithFile(tb testing.TB, file, lib string, opts ...TestOpti
}
}

base := base.GetInitialSensor()

if err = loadSensors(tb, base, sens); err != nil {
if err = loadSensors(tb, initialSensor, sens); err != nil {
return nil, err
}

sens = append(sens, base)
sens = append(sens, initialSensor)
ret := make([]*sensors.Sensor, 0, len(sens))
for _, si := range sens {
if s, ok := si.(*sensors.Sensor); ok {
Expand Down
2 changes: 1 addition & 1 deletion pkg/sensors/config/confmap/confmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func UpdateConfMap(mapDir string, v *TetragonConfValue) error {
return err
}

m, err := program.LoadOrCreatePinnedMap(mapPath, mapSpec)
m, err := program.LoadOrCreatePinnedMap(mapPath, mapSpec, configMap.IsOwner())
if err != nil {
return err
}
Expand Down
42 changes: 31 additions & 11 deletions pkg/sensors/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,6 @@ func (s *Sensor) setMapPinPath(m *program.Map) {
func (s *Sensor) loadMaps(bpfDir string) error {
l := logger.GetLogger()
for _, m := range s.Maps {
// Even if the map already exists we need to setup proper PinPath
// so the loader can have access to the map location.
s.setMapPinPath(m)

if m.PinState.IsLoaded() {
l.WithFields(logrus.Fields{
"sensor": s.Name,
Expand All @@ -262,17 +258,41 @@ func (s *Sensor) loadMaps(bpfDir string) error {
return fmt.Errorf("map '%s' not found from '%s'", m.Name, m.Prog.Name)
}

if max, ok := m.GetMaxEntries(); ok {
s.setMapPinPath(m)
pinPath := filepath.Join(bpfDir, m.PinPath)

if m.IsOwner() {
// If map is the owner we set configured max entries
// directly to map spec.
if max, ok := m.GetMaxEntries(); ok {
mapSpec.MaxEntries = max
}

if innerMax, ok := m.GetMaxInnerEntries(); ok {
if innerMs := mapSpec.InnerMap; innerMs != nil {
mapSpec.InnerMap.MaxEntries = innerMax
}
}
} else {
// If map is NOT the owner we follow the max entries
// of the pinned map and update the spec with that.
max, err := program.GetMaxEntriesPinnedMap(pinPath)
if err != nil {
return err
}
mapSpec.MaxEntries = max
}

if innerMax, ok := m.GetMaxInnerEntries(); ok {
if innerMs := mapSpec.InnerMap; innerMs != nil {
mapSpec.InnerMap.MaxEntries = innerMax
// 'm' is not the owner but for some reason requires max
// entries setup, make sure it matches the pinned map.
if max, ok := m.GetMaxEntries(); ok {
if mapSpec.MaxEntries != max {
return fmt.Errorf("failed to load map '%s' max entries mismatch: %d %d",
m.Name, mapSpec.MaxEntries, max)
}
}
}

pinPath := filepath.Join(bpfDir, m.PinPath)
m.SetMaxEntries(int(max))
}

if err := m.LoadOrCreatePinnedMap(pinPath, mapSpec); err != nil {
return fmt.Errorf("failed to load map '%s' for sensor '%s': %w", m.Name, s.Name, err)
Expand Down
94 changes: 79 additions & 15 deletions pkg/sensors/program/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@
// - map is local for program, not shared at all
//
// NOTE Please do not share MapTypeProgram maps, it brings confusion.
//
// Each map declares the ownership of the map. The map can be either
// owner of the map (via MapBuilder* helpers) or as an user (MapUser*
// helpers.
//
// Map owner object owns the pinned map and when loading it sets (and
// potentially overwrite) the map's spec and its max entries value.
//
// Map user object object is just using the pinned map and follows its
// setup and will fail if the pinned map differs in spec or configured
// max entries value.

package program

Expand Down Expand Up @@ -75,6 +86,11 @@ const (
MapTypeProgram
)

type MapOpts struct {
Type MapType
Owner bool
}

// Map represents BPF maps.
type Map struct {
Name string
Expand All @@ -85,6 +101,7 @@ type Map struct {
Entries MaxEntries
InnerEntries MaxEntries
Type MapType
Owner bool
}

// Map holds pointer to Program object as a source of its ebpf object
Expand All @@ -100,40 +117,64 @@ type Map struct {
// p.PinMap["map2"] = &map2
// ...
// p.PinMap["mapX"] = &mapX
func mapBuilder(name string, ty MapType, lds ...*Program) *Map {
m := &Map{name, "", lds[0], Idle(), nil, MaxEntries{0, false}, MaxEntries{0, false}, ty}
func mapBuilder(name string, ty MapType, owner bool, lds ...*Program) *Map {
m := &Map{name, "", lds[0], Idle(), nil, MaxEntries{0, false}, MaxEntries{0, false}, ty, owner}
for _, ld := range lds {
ld.PinMap[name] = m
}
return m
}

func MapBuilder(name string, lds ...*Program) *Map {
return mapBuilder(name, MapTypeGlobal, lds...)
return mapBuilder(name, MapTypeGlobal, true, lds...)
}

func MapBuilderProgram(name string, lds ...*Program) *Map {
return mapBuilder(name, MapTypeProgram, lds...)
return mapBuilder(name, MapTypeProgram, true, lds...)
}

func MapBuilderSensor(name string, lds ...*Program) *Map {
return mapBuilder(name, MapTypeSensor, lds...)
return mapBuilder(name, MapTypeSensor, true, lds...)
}

func MapBuilderPolicy(name string, lds ...*Program) *Map {
return mapBuilder(name, MapTypePolicy, lds...)
return mapBuilder(name, MapTypePolicy, true, lds...)
}

func MapBuilderType(name string, ty MapType, lds ...*Program) *Map {
return mapBuilder(name, ty, lds...)
return mapBuilder(name, ty, true, lds...)
}

func MapBuilderOpts(name string, opts MapOpts, lds ...*Program) *Map {
return mapBuilder(name, opts.Type, opts.Owner, lds...)
}

func MapUser(name string, lds ...*Program) *Map {
return mapBuilder(name, MapTypeGlobal, false, lds...)
}

func MapUserProgram(name string, lds ...*Program) *Map {
return mapBuilder(name, MapTypeProgram, false, lds...)
}

func MapUserSensor(name string, lds ...*Program) *Map {
return mapBuilder(name, MapTypeSensor, false, lds...)
}

func MapUserPolicy(name string, lds ...*Program) *Map {
return mapBuilder(name, MapTypePolicy, false, lds...)
}

func PolicyMapPath(mapDir, policy, name string) string {
return filepath.Join(mapDir, policy, name)
}

func (m *Map) IsOwner() bool {
return m.Owner
}

func (m *Map) Unload() error {
log := logger.GetLogger().WithField("map", m.Name).WithField("pin", m.Name)
log := logger.GetLogger().WithField("map", m.Name).WithField("pin", m.PinPath)
if !m.PinState.IsLoaded() {
log.WithField("count", m.PinState.count).Debug("Refusing to unload map as it is not loaded")
return nil
Expand Down Expand Up @@ -216,7 +257,7 @@ func (m *Map) LoadOrCreatePinnedMap(pinPath string, mapSpec *ebpf.MapSpec) error
m.MapHandle.Close()
}

mh, err := LoadOrCreatePinnedMap(pinPath, mapSpec)
mh, err := LoadOrCreatePinnedMap(pinPath, mapSpec, m.IsOwner())
if err != nil {
return err
}
Expand All @@ -231,11 +272,12 @@ func isValidSubdir(d string) bool {
return dir != "." && dir != ".."
}

func LoadOrCreatePinnedMap(pinPath string, mapSpec *ebpf.MapSpec) (*ebpf.Map, error) {
func LoadOrCreatePinnedMap(pinPath string, mapSpec *ebpf.MapSpec, create bool) (*ebpf.Map, error) {
var err error
// Try to open the pinPath and if it exist use the previously
// pinned map otherwise pin the map and next user will find
// it here.
if _, err := os.Stat(pinPath); err == nil {
if _, err = os.Stat(pinPath); err == nil {
m, err := ebpf.LoadPinnedMap(pinPath, nil)
if err != nil {
return nil, fmt.Errorf("loading pinned map from path '%s' failed: %w", pinPath, err)
Expand All @@ -244,14 +286,27 @@ func LoadOrCreatePinnedMap(pinPath string, mapSpec *ebpf.MapSpec) (*ebpf.Map, er
logger.GetLogger().WithError(err).WithFields(logrus.Fields{
"path": pinPath,
"map-name": mapSpec.Name,
}).Warn("tetragon, incompatible map found: will delete and recreate")
}).Warn("incompatible map found")
m.Close()
os.Remove(pinPath)
} else {
return m, nil
// If we are creating the map, let's ignore the compatibility error,
// remove the pin and create the map with our spec.
if create {
logger.GetLogger().WithField("map", mapSpec.Name).
Warn("will delete and recreate")
os.Remove(pinPath)
return createPinnedMap(pinPath, mapSpec)
}
return nil, fmt.Errorf("incompatible map '%s'", pinPath)
}
return m, nil
}
if create {
return createPinnedMap(pinPath, mapSpec)
}
return nil, err
}

func createPinnedMap(pinPath string, mapSpec *ebpf.MapSpec) (*ebpf.Map, error) {
// check if PinName has directory portion and create it,
// filepath.Dir returns '.' for filename without dir portion
if dir := filepath.Dir(pinPath); isValidSubdir(dir) {
Expand All @@ -274,6 +329,15 @@ func LoadOrCreatePinnedMap(pinPath string, mapSpec *ebpf.MapSpec) (*ebpf.Map, er
return m, nil
}

func GetMaxEntriesPinnedMap(pinPath string) (uint32, error) {
m, err := ebpf.LoadPinnedMap(pinPath, nil)
if err != nil {
return 0, fmt.Errorf("loading pinned map from path '%s' failed: %w", pinPath, err)
}
defer m.Close()
return m.MaxEntries(), nil
}

func (m *Map) SetMaxEntries(max int) {
m.Entries = MaxEntries{uint32(max), true}
}
Expand Down
Loading

0 comments on commit 64e69f1

Please sign in to comment.