Skip to content

Commit

Permalink
fix(events): fix arm64 tailcalls indexes for unsupported syscalls
Browse files Browse the repository at this point in the history
Bring back the workaround not to index, in tailcall maps, the eBPF
programs with event (syscall) indexes that are unsupported (other
architectures should flag unsupported syscalls with IDs >= 10000).
  • Loading branch information
rafaeldtinoco committed Jul 31, 2023
1 parent 9bae12e commit da0db0d
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 70 deletions.
51 changes: 34 additions & 17 deletions pkg/ebpf/tracee.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,33 +507,50 @@ func (t *Tracee) generateInitValues() (InitValues, error) {

// initTailCall initializes a given tailcall.
func (t *Tracee) initTailCall(tailCall events.TailCall) error {
bpfMap, err := t.bpfModule.GetMap(tailCall.GetMapName())
tailCallMapName := tailCall.GetMapName()
tailCallProgName := tailCall.GetProgName()
tailCallIndexes := tailCall.GetIndexes()

// Pick eBPF map by name.
bpfMap, err := t.bpfModule.GetMap(tailCallMapName)
if err != nil {
return errfmt.WrapError(err)
}
progName := tailCall.GetProgName()
bpfProg, err := t.bpfModule.GetProgram(progName)
// Pick eBPF program by name.
bpfProg, err := t.bpfModule.GetProgram(tailCallProgName)
if err != nil {
return errfmt.Errorf("could not get BPF program %s: %v", progName, err)
return errfmt.Errorf("could not get BPF program %s: %v", tailCallProgName, err)
}
fd := bpfProg.FileDescriptor()
if fd < 0 {
return errfmt.Errorf("could not get BPF program FD for %s: %v", progName, err)
// Pick eBPF program file descriptor.
bpfProgFD := bpfProg.FileDescriptor()
if bpfProgFD < 0 {
return errfmt.Errorf("could not get BPF program FD for %s: %v", tailCallProgName, err)
}

// Attach internal syscall probes if needed.
for _, index := range tailCall.GetIndexes() {
once := &sync.Once{}

// Pick all indexes (event, or syscall, IDs) the BPF program should be related to.
for _, index := range tailCallIndexes {
// Special treatment for indexes of syscall events.
if events.Core.GetDefinitionByID(events.ID(index)).IsSyscall() {
err := t.probes.Attach(probes.SyscallEnter__Internal)
if err != nil {
return errfmt.WrapError(err)
}
err = t.probes.Attach(probes.SyscallExit__Internal)
if err != nil {
return errfmt.WrapError(err)
// Optimization: enable enter/exit probes only if at least one syscall is enabled.
once.Do(func() {
err := t.probes.Attach(probes.SyscallEnter__Internal)
if err != nil {
logger.Errorw("error attaching to syscall enter", "error", err)
}
err = t.probes.Attach(probes.SyscallExit__Internal)
if err != nil {
logger.Errorw("error attaching to syscall enter", "error", err)
}
})
// Workaround: Do not map eBPF program to unsupported syscalls (arm64, e.g.)
if index >= uint32(events.Unsupported) {
continue
}
}
err := bpfMap.Update(unsafe.Pointer(&index), unsafe.Pointer(&fd))
// Update given eBPF map with the eBPF program file descriptor at given index.
err := bpfMap.Update(unsafe.Pointer(&index), unsafe.Pointer(&bpfProgFD))
if err != nil {
return errfmt.WrapError(err)
}
Expand Down
1 change: 1 addition & 0 deletions pkg/events/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
const (
Sys32Undefined ID = 0xfffffff - 1 // u32 overflows are compiler implementation dependent.
Undefined ID = 0xfffffff
Unsupported ID = 10000
)

type ID int32
Expand Down
4 changes: 2 additions & 2 deletions pkg/events/core_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ const (

// following syscalls are undefined on arm64
const (
Open ID = iota + 10000
Open ID = iota + Unsupported
Stat
Lstat
Poll
Expand Down Expand Up @@ -954,7 +954,7 @@ const (

// following syscalls are undefined on arm32
const (
Sys32arch_prctl ID = iota + 10000
Sys32arch_prctl ID = iota + Unsupported
Sys32getpmsg
Sys32putpmsg
Sys32set_thread_area
Expand Down
102 changes: 51 additions & 51 deletions pkg/events/definition_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ func NewDefinitionGroup() *DefinitionGroup {

// GetDefinitions returns a new map of existing definitions.
// TODO: iterate internally after event definition refactor is finished ?
func (e *DefinitionGroup) GetDefinitions() []Definition {
e.mutex.RLock()
defer e.mutex.RUnlock()
func (d *DefinitionGroup) GetDefinitions() []Definition {
d.mutex.RLock()
defer d.mutex.RUnlock()

definitions := make([]Definition, 0, len(e.definitions))
for _, def := range e.definitions {
definitions := make([]Definition, 0, len(d.definitions))
for _, def := range d.definitions {
definitions = append(definitions, def)
}
sort.Sort(ByID(definitions))
Expand All @@ -57,15 +57,15 @@ func (e *DefinitionGroup) GetDefinitions() []Definition {
}

// GetDefinitionIDByName returns a definition ID by its name.
func (e *DefinitionGroup) GetDefinitionIDByName(givenName string) (ID, bool) {
e.mutex.RLock()
defer e.mutex.RUnlock()
return e.getDefinitionIDByName(givenName)
func (d *DefinitionGroup) GetDefinitionIDByName(givenName string) (ID, bool) {
d.mutex.RLock()
defer d.mutex.RUnlock()
return d.getDefinitionIDByName(givenName)
}

// getDefinitionIDByName returns a definition ID by its name (no locking).
func (e *DefinitionGroup) getDefinitionIDByName(givenName string) (ID, bool) {
for id, def := range e.definitions {
func (d *DefinitionGroup) getDefinitionIDByName(givenName string) (ID, bool) {
for id, def := range d.definitions {
if def.GetName() == givenName {
return id, true
}
Expand All @@ -77,11 +77,11 @@ func (e *DefinitionGroup) getDefinitionIDByName(givenName string) (ID, bool) {

// GetDefinitionByID returns a definition by its ID.
// NOTE: should be used together with IsDefined when definition might not exist.
func (e *DefinitionGroup) GetDefinitionByID(givenDef ID) Definition {
e.mutex.RLock()
defer e.mutex.RUnlock()
func (d *DefinitionGroup) GetDefinitionByID(givenDef ID) Definition {
d.mutex.RLock()
defer d.mutex.RUnlock()

def, ok := e.definitions[givenDef]
def, ok := d.definitions[givenDef]
if !ok {
logger.Debugw("definition id not found", "id", givenDef)
return Definition{id: Undefined}
Expand All @@ -92,35 +92,35 @@ func (e *DefinitionGroup) GetDefinitionByID(givenDef ID) Definition {

// IsDefined returns true if the definition exists in the definition group.
// NOTE: needed as GetDefinitionByID() is used as GetDefinitionByID().Method() multiple times.
func (e *DefinitionGroup) IsDefined(givenDef ID) bool {
e.mutex.RLock()
defer e.mutex.RUnlock()
func (d *DefinitionGroup) IsDefined(givenDef ID) bool {
d.mutex.RLock()
defer d.mutex.RUnlock()

_, ok := e.definitions[givenDef]
_, ok := d.definitions[givenDef]
return ok
}

// Length returns the number of definitions in the definition group.
func (e *DefinitionGroup) Length() int {
e.mutex.RLock()
defer e.mutex.RUnlock()
return len(e.definitions)
func (d *DefinitionGroup) Length() int {
d.mutex.RLock()
defer d.mutex.RUnlock()
return len(d.definitions)
}

// Add adds a definition to the definition group.
func (e *DefinitionGroup) Add(givenId ID, givenDef Definition) error {
e.mutex.Lock()
defer e.mutex.Unlock()
return e.add(givenId, givenDef)
func (d *DefinitionGroup) Add(givenId ID, givenDef Definition) error {
d.mutex.Lock()
defer d.mutex.Unlock()
return d.add(givenId, givenDef)
}

// AddBatch adds multiple definitions to the definition group.
func (e *DefinitionGroup) AddBatch(givenDefs map[ID]Definition) error {
e.mutex.Lock()
defer e.mutex.Unlock()
func (d *DefinitionGroup) AddBatch(givenDefs map[ID]Definition) error {
d.mutex.Lock()
defer d.mutex.Unlock()

for id, def := range givenDefs {
err := e.add(id, def)
err := d.add(id, def)
if err != nil {
return err
}
Expand All @@ -130,43 +130,43 @@ func (e *DefinitionGroup) AddBatch(givenDefs map[ID]Definition) error {
}

// add adds a definition to the definition group (no locking).
func (e *DefinitionGroup) add(givenId ID, givenDef Definition) error {
if _, ok := e.definitions[givenId]; ok {
func (d *DefinitionGroup) add(givenId ID, givenDef Definition) error {
if _, ok := d.definitions[givenId]; ok {
return definitionIDAlreadyExistsErr(givenId)
}

n := givenDef.GetName()
if _, ok := e.getDefinitionIDByName(n); ok {
if _, ok := d.getDefinitionIDByName(n); ok {
return definitionNameAlreadyExistsErr(n)
}

e.definitions[givenId] = givenDef
d.definitions[givenId] = givenDef

return nil
}

// NamesToIDs returns a new map of definition names to their IDs.
func (e *DefinitionGroup) NamesToIDs() map[string]ID {
e.mutex.RLock()
defer e.mutex.RUnlock()
func (d *DefinitionGroup) NamesToIDs() map[string]ID {
d.mutex.RLock()
defer d.mutex.RUnlock()

namesToIds := make(map[string]ID, len(e.definitions))
namesToIds := make(map[string]ID, len(d.definitions))

for id, def := range e.definitions {
for id, def := range d.definitions {
namesToIds[def.GetName()] = id
}

return namesToIds
}

// IDs32ToIDs returns a new map of 32-bit definition IDs to their IDs.
func (e *DefinitionGroup) IDs32ToIDs() map[ID]ID {
e.mutex.RLock()
defer e.mutex.RUnlock()
func (d *DefinitionGroup) IDs32ToIDs() map[ID]ID {
d.mutex.RLock()
defer d.mutex.RUnlock()

idS32ToIDs := make(map[ID]ID, len(e.definitions))
idS32ToIDs := make(map[ID]ID, len(d.definitions))

for id, def := range e.definitions {
for id, def := range d.definitions {
id32Bit := def.GetID32Bit()

if id32Bit != Sys32Undefined {
Expand All @@ -178,15 +178,15 @@ func (e *DefinitionGroup) IDs32ToIDs() map[ID]ID {
}

// GetTailCalls returns a list of tailcalls of all definitions in the group (for initialization).
func (e *DefinitionGroup) GetTailCalls(state map[ID]EventState) []TailCall {
e.mutex.RLock()
defer e.mutex.RUnlock()
func (d *DefinitionGroup) GetTailCalls(state map[ID]EventState) []TailCall {
d.mutex.RLock()
defer d.mutex.RUnlock()

var tailCalls []TailCall

for id, def := range e.definitions {
if state[id].Submit > 0 { // only traced events to provide their tailcalls
tailCalls = append(tailCalls, def.GetDependencies().GetTailCalls()...)
for evtDefID, evtDef := range d.definitions {
if state[evtDefID].Submit > 0 { // only traced events to provide their tailcalls
tailCalls = append(tailCalls, evtDef.GetDependencies().GetTailCalls()...)
}
}

Expand Down

0 comments on commit da0db0d

Please sign in to comment.