Skip to content

tetragon: Check and remove not compatible map pin paths on loading #543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions pkg/sensors/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,23 +181,39 @@ func (s *Sensor) LoadMaps(stopCtx context.Context, mapDir string) error {
}
}

spec, err := ebpf.LoadCollectionSpec(m.Prog.Name)
if err != nil {
return fmt.Errorf("failed to open collection '%s': %w", m.Prog.Name, err)
}
mapSpec, ok := spec.Maps[m.Name]
if !ok {
return fmt.Errorf("map '%s' not found from '%s'", m.Name, m.Prog.Name)
}

createMap := true

// 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 = m.LoadPinnedMap(pinPath); err != nil {
return fmt.Errorf("loading pinned map failed: %w", err)
}
} else {
spec, err := ebpf.LoadCollectionSpec(m.Prog.Name)
if err != nil {
return fmt.Errorf("failed to open collection '%s': %w", m.Prog.Name, err)
}
mapSpec, ok := spec.Maps[m.Name]
if !ok {
return fmt.Errorf("map '%s' not found from '%s'", m.Name, m.Prog.Name)
if err = m.IsCompatibleWith(mapSpec); err != nil {
l.WithFields(logrus.Fields{
"sensor": s.Name,
"map": m.Name,
"path": pinPath,
}).Warn("tetragon, incompatible map found: ", err)
m.Close()
os.Remove(pinPath)
} else {
createMap = false
}
}

// either there's no pin file or the map spec does not match
if createMap {
if err := m.New(mapSpec); err != nil {
return fmt.Errorf("failed to open map '%s': %w", m.Name, err)
}
Expand Down
27 changes: 27 additions & 0 deletions pkg/sensors/program/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,33 @@ func (m *Map) LoadPinnedMap(path string) error {
return err
}

// MapSpec.Compatible will be exported in ebpf v0.9.3,
// meanwhile steal that and make it our own ;-)
func compatible(ms *ebpf.MapSpec, m *ebpf.Map) error {
switch {
case m.Type() != ms.Type:
return fmt.Errorf("expected type %v, got %v: %w", ms.Type, m.Type(), ebpf.ErrMapIncompatible)

case m.KeySize() != ms.KeySize:
return fmt.Errorf("expected key size %v, got %v: %w", ms.KeySize, m.KeySize(), ebpf.ErrMapIncompatible)

case m.ValueSize() != ms.ValueSize:
return fmt.Errorf("expected value size %v, got %v: %w", ms.ValueSize, m.ValueSize(), ebpf.ErrMapIncompatible)

case !(ms.Type == ebpf.PerfEventArray && ms.MaxEntries == 0) &&
m.MaxEntries() != ms.MaxEntries:
return fmt.Errorf("expected max entries %v, got %v: %w", ms.MaxEntries, m.MaxEntries(), ebpf.ErrMapIncompatible)

case m.Flags() != ms.Flags:
return fmt.Errorf("expected flags %v, got %v: %w", ms.Flags, m.Flags(), ebpf.ErrMapIncompatible)
}
return nil
}

func (m *Map) IsCompatibleWith(spec *ebpf.MapSpec) error {
return compatible(spec, m.MapHandle)
}

func (m *Map) Close() error {
return m.MapHandle.Close()
}
Expand Down