Skip to content

tetragon: group enable process ancestors flags #3581

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 7 additions & 1 deletion contrib/upgrade-notes/latest.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
Read the upgrade notes carefully before upgrading Tetragon.
Depending on your setup, changes listed here might require a manual intervention.

* TBD
* Enabling ancestors for process events is now configured by a new `--enable-ancestors` flag.
The following flags are being deprecarted in this (1.5) and are scheduled for removal in the next (1.6):
* `--enable-process-ancestors`
* `--enable-process-kprobe-ancestors`
* `--enable-process-tracepoint-ancestors`
* `--enable-process-uprobe-ancestors`
* `--enable-process-lsm-ancestors`

### Agent Options

Expand Down
1 change: 1 addition & 0 deletions docs/content/en/docs/reference/helm-chart.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions docs/data/tetragon_flags.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions examples/configuration/tetragon.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ debug: false
disable-kprobe-multi: false
enable-export-aggregation: false
enable-k8s-api: false
enable-process-ancestors: false
enable-process-kprobe-ancestors: false
enable-process-tracepoint-ancestors: false
enable-process-uprobe-ancestors: false
enable-process-lsm-ancestors: false
enable-ancestors: "base,kprobe,tracepoint,uprobe,lsm"
enable-process-cred: false
enable-process-ns: false
event-queue-size: 10000
Expand Down
1 change: 1 addition & 0 deletions install/kubernetes/tetragon/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ data:
debug: {{ .Values.tetragon.debug | quote }}
enable-process-cred: {{ .Values.tetragon.enableProcessCred | quote }}
enable-process-ns: {{ .Values.tetragon.enableProcessNs | quote }}
enable-ancestors: {{ .Values.tetragon.processAncestors.enabled }}
process-cache-size: {{ .Values.tetragon.processCacheSize | quote }}
{{- if .Values.tetragon.exportFilename }}
export-filename: {{ .Values.exportDirectory}}/{{ .Values.tetragon.exportFilename }}
Expand Down
6 changes: 6 additions & 0 deletions install/kubernetes/tetragon/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ tetragon:
enableProcessCred: false
# -- Enable Namespaces visibility in exec and kprobe events.
enableProcessNs: false
processAncestors:
# -- Comma-separated list of process event types to enable ancestors for.
# Supported event types are: base, kprobe, tracepoint, uprobe, lsm. Unknown event types will be ignored.
# Type "base" is required by all other supported event types for correct reference counting.
# Set it to "" to disable ancestors completely.
enabled: ""
# -- Set --btf option to explicitly specify an absolute path to a btf file. For advanced users only.
btf: ""
# -- Override the command. For advanced users only.
Expand Down
18 changes: 2 additions & 16 deletions pkg/eventcache/eventcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,15 @@ var (
ErrFailedToGetAncestorsInfo = errors.New("failed to get ancestors info from event cache")
)

func enabledAncestors(ev notify.Event) bool {
switch ev.(type) {
case *tetragon.ProcessKprobe:
return option.Config.EnableProcessKprobeAncestors
case *tetragon.ProcessTracepoint:
return option.Config.EnableProcessTracepointAncestors
case *tetragon.ProcessUprobe:
return option.Config.EnableProcessUprobeAncestors
case *tetragon.ProcessLsm:
return option.Config.EnableProcessLsmAncestors
default:
return false
}
}

// Generic internal lookup happens when events are received out of order and
// this event was handled before an exec event so it wasn't able to populate
// the process info yet.
func HandleGenericInternal(ev notify.Event, pid uint32, tid *uint32, timestamp uint64) (*process.ProcessInternal, error) {
internal, parent := process.GetParentProcessInternal(pid, timestamp)
var err error

if enabledAncestors(ev) && internal.NeededAncestors() {
eventType := notify.EventType(ev)
if option.Config.EnableAncestors[option.AncestorsEventTypeMap[eventType]] && internal.NeededAncestors() {
// We do not need to try to recollect all ancestors starting from the immediate parent here,
// if we already collected some of them in previous attempts. So, if we already have a number
// of ancestors collected, we just need to try to resume the collection process from the last
Expand Down
2 changes: 1 addition & 1 deletion pkg/filters/binary_regex.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func filterByBinaryRegex(binaryPatterns []string, level int) (hubbleFilters.Filt
case ancestorBinary:
processes = GetAncestors(ev)
}
if processes == nil || processes[0] == nil {
if len(processes) == 0 || processes[0] == nil {
return false
}
for _, process := range processes {
Expand Down
32 changes: 3 additions & 29 deletions pkg/filters/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,39 +161,13 @@ func GetPolicyName(event *v1.Event) string {
}
}

var AncestorsEventSet = []tetragon.EventType{
tetragon.EventType_PROCESS_EXEC,
tetragon.EventType_PROCESS_EXIT,
tetragon.EventType_PROCESS_KPROBE,
tetragon.EventType_PROCESS_TRACEPOINT,
tetragon.EventType_PROCESS_UPROBE,
tetragon.EventType_PROCESS_LSM,
}

func enabledAncestors(eventType tetragon.EventType) bool {
switch eventType {
case tetragon.EventType_PROCESS_EXEC, tetragon.EventType_PROCESS_EXIT:
return option.Config.EnableProcessAncestors
case tetragon.EventType_PROCESS_KPROBE:
return option.Config.EnableProcessKprobeAncestors
case tetragon.EventType_PROCESS_TRACEPOINT:
return option.Config.EnableProcessTracepointAncestors
case tetragon.EventType_PROCESS_UPROBE:
return option.Config.EnableProcessUprobeAncestors
case tetragon.EventType_PROCESS_LSM:
return option.Config.EnableProcessLsmAncestors
default:
return false
}
}

func CheckAncestorsEnabled(types []tetragon.EventType) error {
if types == nil {
types = AncestorsEventSet
if len(types) == 0 {
types = option.GetAncestorsEventTypes()
}

for _, eventType := range types {
if !enabledAncestors(eventType) {
if !option.Config.EnableAncestors[option.AncestorsEventTypeMap[eventType]] {
return fmt.Errorf("ancestors are not enabled for %s event type, cannot configure ancestor filter", eventType)
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/filters/filters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
func TestMain(m *testing.M) {
// Needed for cap filters
option.Config.EnableProcessCred = true
option.Config.EnableProcessAncestors = true
option.Config.EnableAncestors = option.AncestorsEventFilter{"base": true}

code := m.Run()
os.Exit(code)
Expand Down
36 changes: 18 additions & 18 deletions pkg/grpc/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ func GetProcessExec(event *MsgExecveEventUnix, useCache bool) *tetragon.ProcessE
tetragonParent = parent.UnsafeGetProcess()
}

// Set the ancestors only if --enable-process-ancestors flag is set.
if option.Config.EnableProcessAncestors && proc.NeededAncestors() {
// Set the ancestors only if --enable-ancestors flag includes 'base'.
if option.Config.EnableAncestors["base"] && proc.NeededAncestors() {
// We don't care about an error here, because later we call ec.NeededAncestors,
// that will determine if we were successful in collecting all ancestors and,
// if we were not, the event will be added to the event cache for reprocessing.
Expand Down Expand Up @@ -89,13 +89,13 @@ func GetProcessExec(event *MsgExecveEventUnix, useCache bool) *tetragon.ProcessE
if ec := eventcache.Get(); ec != nil &&
(ec.Needed(tetragonProcess) ||
(tetragonProcess.Pid.Value > 1 && ec.Needed(tetragonParent)) ||
(option.Config.EnableProcessAncestors && ec.NeededAncestors(parent, ancestors))) {
(option.Config.EnableAncestors["base"] && ec.NeededAncestors(parent, ancestors))) {
ec.Add(proc, tetragonEvent, event.Unix.Msg.Common.Ktime, event.Unix.Process.Ktime, event)
return nil
}
}

if option.Config.EnableProcessAncestors {
if option.Config.EnableAncestors["base"] {
for _, ancestor := range ancestors {
ancestor.RefInc("ancestor")
}
Expand Down Expand Up @@ -239,7 +239,7 @@ func (msg *MsgExecveEventUnix) Retry(internal *process.ProcessInternal, ev notif
// ancestors of the given process, including the immediate parent. So in order for us
// to collect ancestors beyond immediate parent, we need to pass immediate parent to
// GetAncestorProcessesInternal.
if option.Config.EnableProcessAncestors && internal.NeededAncestors() && !msg.RefCntDone[AncestorsRefCnt] {
if option.Config.EnableAncestors["base"] && internal.NeededAncestors() && !msg.RefCntDone[AncestorsRefCnt] {
if ancestors, err := process.GetAncestorProcessesInternal(tetragonProcess.ParentExecId); err == nil {
var tetragonAncestors []*tetragon.Process
for _, ancestor := range ancestors {
Expand Down Expand Up @@ -354,7 +354,7 @@ func (msg *MsgCloneEventUnix) Retry(internal *process.ProcessInternal, _ notify.
internal.AddPodInfo(podInfo)
}

if option.Config.EnableProcessAncestors && internal.NeededAncestors() {
if option.Config.EnableAncestors["base"] && internal.NeededAncestors() {
if ancestors, err := process.GetAncestorProcessesInternal(tetragonProcess.ParentExecId); err == nil {
for _, ancestor := range ancestors {
ancestor.RefInc("ancestor")
Expand All @@ -372,7 +372,7 @@ func (msg *MsgCloneEventUnix) HandleMessage() *tetragon.GetEventsResponse {
var ancestors []*process.ProcessInternal

proc, _ := process.AddCloneEvent(&msg.MsgCloneEvent)
if option.Config.EnableProcessAncestors && proc.NeededAncestors() {
if option.Config.EnableAncestors["base"] && proc.NeededAncestors() {
ancestors, _ = process.GetAncestorProcessesInternal(proc.UnsafeGetProcess().ParentExecId)
}

Expand All @@ -386,14 +386,14 @@ func (msg *MsgCloneEventUnix) HandleMessage() *tetragon.GetEventsResponse {
parent, _ := process.Get(proc.UnsafeGetProcess().ParentExecId)

if ec.Needed(proc.UnsafeGetProcess()) ||
option.Config.EnableProcessAncestors && ec.NeededAncestors(parent, ancestors) {
option.Config.EnableAncestors["base"] && ec.NeededAncestors(parent, ancestors) {
// adding to the cache due to missing pod info or ancestors
ec.Add(proc, nil, msg.Common.Ktime, msg.Ktime, msg)
return nil
}
}

if option.Config.EnableProcessAncestors {
if option.Config.EnableAncestors["base"] {
for _, ancestor := range ancestors {
ancestor.RefInc("ancestor")
}
Expand Down Expand Up @@ -425,8 +425,8 @@ func GetProcessExit(event *MsgExitEventUnix) *tetragon.ProcessExit {
tetragonParent = parent.UnsafeGetProcess()
}

// Set the ancestors only if --enable-process-ancestors flag is set.
if option.Config.EnableProcessAncestors && proc.NeededAncestors() {
// Set the ancestors only if --enable-ancestors flag includes 'base'.
if option.Config.EnableAncestors["base"] && proc.NeededAncestors() {
// We don't care about an error here, because later we call ec.NeededAncestors,
// that will determine if we were successful in collecting all ancestors and,
// if we were not, the event will be added to the event cache for reprocessing.
Expand Down Expand Up @@ -492,12 +492,12 @@ func GetProcessExit(event *MsgExitEventUnix) *tetragon.ProcessExit {
if ec := eventcache.Get(); ec != nil &&
(ec.Needed(tetragonProcess) ||
(tetragonProcess.Pid.Value > 1 && ec.Needed(tetragonParent)) ||
(option.Config.EnableProcessAncestors && ec.NeededAncestors(parent, ancestors))) {
(option.Config.EnableAncestors["base"] && ec.NeededAncestors(parent, ancestors))) {
ec.Add(nil, tetragonEvent, event.Common.Ktime, event.ProcessKey.Ktime, event)
return nil
}

if option.Config.EnableProcessAncestors {
if option.Config.EnableAncestors["base"] {
for _, ancestor := range ancestors {
ancestor.RefDec("ancestor")
}
Expand All @@ -524,7 +524,7 @@ func (msg *MsgExitEventUnix) RetryInternal(ev notify.Event, timestamp uint64) (*
proc, parent := process.GetParentProcessInternal(msg.ProcessKey.Pid, timestamp)
var err error

if option.Config.EnableProcessAncestors && proc.NeededAncestors() && !msg.RefCntDone[AncestorsRefCnt] {
if option.Config.EnableAncestors["base"] && proc.NeededAncestors() && !msg.RefCntDone[AncestorsRefCnt] {
if ancestors, perr := process.GetAncestorProcessesInternal(proc.UnsafeGetProcess().ParentExecId); perr == nil {
var tetragonAncestors []*tetragon.Process
for _, ancestor := range ancestors {
Expand Down Expand Up @@ -605,7 +605,7 @@ func (msg *MsgProcessCleanupEventUnix) RetryInternal(_ notify.Event, timestamp u
proc, parent := process.GetParentProcessInternal(msg.PID, timestamp)
var err error

if option.Config.EnableProcessAncestors && proc.NeededAncestors() && !msg.RefCntDone[AncestorsRefCnt] {
if option.Config.EnableAncestors["base"] && proc.NeededAncestors() && !msg.RefCntDone[AncestorsRefCnt] {
if ancestors, perr := process.GetAncestorProcessesInternal(proc.UnsafeGetProcess().ParentExecId); perr == nil {
for _, ancestor := range ancestors {
ancestor.RefDec("ancestor")
Expand Down Expand Up @@ -652,19 +652,19 @@ func (msg *MsgProcessCleanupEventUnix) HandleMessage() *tetragon.GetEventsRespon

msg.RefCntDone = [3]bool{false, false, false}
proc, parent := process.GetParentProcessInternal(msg.PID, msg.Ktime)
if option.Config.EnableProcessAncestors && proc.NeededAncestors() {
if option.Config.EnableAncestors["base"] && proc.NeededAncestors() {
ancestors, _ = process.GetAncestorProcessesInternal(proc.UnsafeGetProcess().ParentExecId)
}

if ec := eventcache.Get(); ec != nil &&
(proc == nil ||
parent == nil ||
option.Config.EnableProcessAncestors && ec.NeededAncestors(parent, ancestors)) {
option.Config.EnableAncestors["base"] && ec.NeededAncestors(parent, ancestors)) {
ec.Add(nil, nil, msg.Ktime, msg.Ktime, msg)
return nil
}

if option.Config.EnableProcessAncestors {
if option.Config.EnableAncestors["base"] {
for _, ancestor := range ancestors {
ancestor.RefDec("ancestor")
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/grpc/exec/exec_test_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,7 @@ func GrpcDelayedExecK8sOutOfOrder[EXEC notify.Message, EXIT notify.Message](t *t
}

func GrpcExecAncestorsInOrder[EXEC notify.Message, CLONE notify.Message, EXIT notify.Message](t *testing.T) {
option.Config.EnableProcessAncestors = true // enable Ancestors
option.Config.EnableAncestors = option.AncestorsEventFilter{"base": true} // enable Ancestors
AllEvents = nil
watcher := watcher.NewFakeK8sWatcher(nil)
dn := InitEnv[EXEC, EXIT](t, watcher)
Expand Down Expand Up @@ -1280,7 +1280,7 @@ func GrpcExecAncestorsInOrder[EXEC notify.Message, CLONE notify.Message, EXIT no
}

func GrpcExecAncestorsOutOfOrder[EXEC notify.Message, CLONE notify.Message, EXIT notify.Message](t *testing.T) {
option.Config.EnableProcessAncestors = true // enable Ancestors
option.Config.EnableAncestors = option.AncestorsEventFilter{"base": true} // enable Ancestors
AllEvents = nil
watcher := watcher.NewFakeK8sWatcher(nil)
dn := InitEnv[EXEC, EXIT](t, watcher)
Expand Down
Loading
Loading