Skip to content
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

[backport v1.1] pkg/sensors: reduce memory footprint of unused fdinstall maps and various fixes #2693

Merged
merged 3 commits into from
Jul 19, 2024
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
2 changes: 1 addition & 1 deletion bpf/process/types/basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1901,7 +1901,7 @@ struct fdinstall_value {

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, 32000);
__uint(max_entries, 1); // will be resized by agent when needed
__type(key, struct fdinstall_key);
__type(value, struct fdinstall_value);
} fdinstall_map SEC(".maps");
Expand Down
72 changes: 58 additions & 14 deletions pkg/sensors/tracing/generickprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const (
// much kernel memory when enabled.
stackTraceMapMaxEntries = 32768
ratelimitMapMaxEntries = 32768
fdInstallMapMaxEntries = 32000
)

func kprobeCharBufErrorToString(e int32) string {
Expand Down Expand Up @@ -271,7 +272,7 @@ func filterMaps(load *program.Program, pinPath string, kprobeEntry *genericKprob
return maps
}

func createMultiKprobeSensor(sensorPath, policyName string, multiIDs []idtable.EntryID) ([]*program.Program, []*program.Map, error) {
func createMultiKprobeSensor(sensorPath, policyName string, multiIDs []idtable.EntryID, enableFDInstall bool) ([]*program.Program, []*program.Map, error) {
var multiRetIDs []idtable.EntryID
var progs []*program.Program
var maps []*program.Map
Expand Down Expand Up @@ -315,6 +316,9 @@ func createMultiKprobeSensor(sensorPath, policyName string, multiIDs []idtable.E
progs = append(progs, load)

fdinstall := program.MapBuilderPin("fdinstall_map", sensors.PathJoin(sensorPath, "fdinstall_map"), load)
if enableFDInstall {
fdinstall.SetMaxEntries(fdInstallMapMaxEntries)
}
maps = append(maps, fdinstall)

configMap := program.MapBuilderPin("config_map", sensors.PathJoin(pinPath, "config_map"), load)
Expand Down Expand Up @@ -392,6 +396,9 @@ func createMultiKprobeSensor(sensorPath, policyName string, multiIDs []idtable.E
maps = append(maps, callHeap)

fdinstall := program.MapBuilderPin("fdinstall_map", sensors.PathJoin(sensorPath, "fdinstall_map"), loadret)
if enableFDInstall {
fdinstall.SetMaxEntries(fdInstallMapMaxEntries)
}
maps = append(maps, fdinstall)

socktrack := program.MapBuilderPin("socktrack_map", sensors.PathJoin(sensorPath, "socktrack_map"), loadret)
Expand Down Expand Up @@ -578,6 +585,16 @@ func createGenericKprobeSensor(
selMaps = &selectors.KernelSelectorMaps{}
}

// detect at the policy level if one kprobe uses the fdinstall feature since
// the map is shared amongst all kprobes
oneKprobeHasFDInstall := false
for _, kprobe := range kprobes {
if selectorsHaveFDInstall(kprobe.Selectors) {
oneKprobeHasFDInstall = true
break
}
}

in := addKprobeIn{
useMulti: useMulti,
sensorPath: name,
Expand Down Expand Up @@ -606,9 +623,9 @@ func createGenericKprobeSensor(
}

if useMulti {
progs, maps, err = createMultiKprobeSensor(in.sensorPath, in.policyName, ids)
progs, maps, err = createMultiKprobeSensor(in.sensorPath, in.policyName, ids, oneKprobeHasFDInstall)
} else {
progs, maps, err = createSingleKprobeSensor(in.sensorPath, ids)
progs, maps, err = createSingleKprobeSensor(in.sensorPath, ids, oneKprobeHasFDInstall)
}

if err != nil {
Expand Down Expand Up @@ -646,6 +663,10 @@ func addKprobe(funcName string, f *v1alpha1.KProbeSpec, in *addKprobeIn) (id idt
return idtable.UninitializedEntryID, err
}

if f == nil {
return errFn(errors.New("error adding kprobe, the kprobe spec is nil"))
}

config := &api.EventConfig{}
config.PolicyID = uint32(in.policyID)
if len(f.ReturnArgAction) > 0 {
Expand Down Expand Up @@ -781,13 +802,6 @@ func addKprobe(funcName string, f *v1alpha1.KProbeSpec, in *addKprobeIn) (id idt
config.Syscall = 0
}

hasStackTrace := false
for _, selector := range f.Selectors {
for _, matchAction := range selector.MatchActions {
hasStackTrace = matchAction.KernelStackTrace || matchAction.UserStackTrace
}
}

// create a new entry on the table, and pass its id to BPF-side
// so that we can do the matching at event-generation time
kprobeEntry := genericKprobe{
Expand All @@ -806,7 +820,7 @@ func addKprobe(funcName string, f *v1alpha1.KProbeSpec, in *addKprobeIn) (id idt
customHandler: in.customHandler,
message: msgField,
tags: tagsField,
hasStackTrace: hasStackTrace,
hasStackTrace: selectorsHaveStackTrace(f.Selectors),
hasRatelimit: selectorsHaveRateLimit(f.Selectors),
}

Expand Down Expand Up @@ -848,7 +862,7 @@ func addKprobe(funcName string, f *v1alpha1.KProbeSpec, in *addKprobeIn) (id idt
}

func createKprobeSensorFromEntry(kprobeEntry *genericKprobe, sensorPath string,
progs []*program.Program, maps []*program.Map) ([]*program.Program, []*program.Map) {
progs []*program.Program, maps []*program.Map, enableFDInstall bool) ([]*program.Program, []*program.Map) {

loadProgName, loadProgRetName := kernels.GenericKprobeObjs()
isSecurityFunc := strings.HasPrefix(kprobeEntry.funcName, "security_")
Expand All @@ -870,6 +884,9 @@ func createKprobeSensorFromEntry(kprobeEntry *genericKprobe, sensorPath string,
progs = append(progs, load)

fdinstall := program.MapBuilderPin("fdinstall_map", sensors.PathJoin(sensorPath, "fdinstall_map"), load)
if enableFDInstall {
fdinstall.SetMaxEntries(fdInstallMapMaxEntries)
}
maps = append(maps, fdinstall)

configMap := program.MapBuilderPin("config_map", sensors.PathJoin(pinPath, "config_map"), load)
Expand Down Expand Up @@ -961,6 +978,9 @@ func createKprobeSensorFromEntry(kprobeEntry *genericKprobe, sensorPath string,
maps = append(maps, callHeap)

fdinstall := program.MapBuilderPin("fdinstall_map", sensors.PathJoin(sensorPath, "fdinstall_map"), loadret)
if enableFDInstall {
fdinstall.SetMaxEntries(fdInstallMapMaxEntries)
}
maps = append(maps, fdinstall)

if kernels.EnableLargeProgs() {
Expand All @@ -974,7 +994,7 @@ func createKprobeSensorFromEntry(kprobeEntry *genericKprobe, sensorPath string,
return progs, maps
}

func createSingleKprobeSensor(sensorPath string, ids []idtable.EntryID) ([]*program.Program, []*program.Map, error) {
func createSingleKprobeSensor(sensorPath string, ids []idtable.EntryID, enableFDInstall bool) ([]*program.Program, []*program.Map, error) {
var progs []*program.Program
var maps []*program.Map

Expand All @@ -984,7 +1004,7 @@ func createSingleKprobeSensor(sensorPath string, ids []idtable.EntryID) ([]*prog
return nil, nil, err
}
gk.data = &genericKprobeData{}
progs, maps = createKprobeSensorFromEntry(gk, sensorPath, progs, maps)
progs, maps = createKprobeSensorFromEntry(gk, sensorPath, progs, maps, enableFDInstall)
}

return progs, maps, nil
Expand Down Expand Up @@ -1312,3 +1332,27 @@ func selectorsHaveRateLimit(selectors []v1alpha1.KProbeSelector) bool {
}
return false
}

func selectorsHaveStackTrace(selectors []v1alpha1.KProbeSelector) bool {
for _, selector := range selectors {
for _, matchAction := range selector.MatchActions {
if matchAction.KernelStackTrace || matchAction.UserStackTrace {
return true
}
}
}
return false
}

func selectorsHaveFDInstall(sel []v1alpha1.KProbeSelector) bool {
for _, selector := range sel {
for _, matchAction := range selector.MatchActions {
if a := selectors.ActionTypeFromString(matchAction.Action); a == selectors.ActionTypeFollowFd ||
a == selectors.ActionTypeUnfollowFd ||
a == selectors.ActionTypeCopyFd {
return true
}
}
}
return false
}
7 changes: 7 additions & 0 deletions pkg/sensors/tracing/generictracepoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ func createGenericTracepoint(
policyName string,
customHandler eventhandler.Handler,
) (*genericTracepoint, error) {
if conf == nil {
return nil, errors.New("failed creating generic tracepoint, conf is nil")
}

tp := tracepoint.Tracepoint{
Subsys: conf.Subsystem,
Event: conf.Event,
Expand Down Expand Up @@ -405,6 +409,9 @@ func createGenericTracepointSensor(
progs = append(progs, prog0)

fdinstall := program.MapBuilderPin("fdinstall_map", sensors.PathJoin(pinPath, "fdinstall_map"), prog0)
if selectorsHaveFDInstall(tp.Spec.Selectors) {
fdinstall.SetMaxEntries(fdInstallMapMaxEntries)
}
maps = append(maps, fdinstall)

tailCalls := program.MapBuilderPin("tp_calls", sensors.PathJoin(pinPath, "tp_calls"), prog0)
Expand Down
Loading