From 110e495c261f6662559cde897f6bfe9a1bd6c631 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian Date: Mon, 21 Sep 2026 16:05:36 +0200 Subject: [PATCH 1/5] feat(filter): Extract conservative equality, list, and prefix prefilters --- pkg/filter/approver.go | 569 +++++++++++++++++++++++++ pkg/filter/approver_fuzz_linux_test.go | 114 +++++ pkg/filter/approver_linux.go | 36 ++ pkg/filter/approver_linux_test.go | 140 ++++++ pkg/filter/approver_windows.go | 27 ++ pkg/rules/compiler.go | 27 ++ pkg/rules/compiler_linux_test.go | 68 ++- pkg/rules/engine.go | 10 + 8 files changed, 990 insertions(+), 1 deletion(-) create mode 100644 pkg/filter/approver.go create mode 100644 pkg/filter/approver_fuzz_linux_test.go create mode 100644 pkg/filter/approver_linux.go create mode 100644 pkg/filter/approver_linux_test.go create mode 100644 pkg/filter/approver_windows.go diff --git a/pkg/filter/approver.go b/pkg/filter/approver.go new file mode 100644 index 000000000..12b4bb42e --- /dev/null +++ b/pkg/filter/approver.go @@ -0,0 +1,569 @@ +/* + * Copyright 2026 by Mostafa Moradian + * https://www.fibratus.io + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package filter + +import ( + "slices" + "strconv" + "strings" + + "github.com/rabbitstack/fibratus/pkg/event" + "github.com/rabbitstack/fibratus/pkg/filter/fields" + "github.com/rabbitstack/fibratus/pkg/filter/ql" +) + +// ApproverProvider is an optional filter capability that exposes a +// conservative, kernel-safe extraction of positive predicates. Filters +// that do not implement it are treated as unextractable, which forces +// default-allow for every event type they could match. +type ApproverProvider interface { + ApproverExtraction() Extraction +} + +// Extraction is the conservative predicate set taken from one compiled +// filter. Unsupported is set when the AST contains a shape that cannot +// be proven as a superset of matches (OR, NOT, inequality, regex, range, +// function, bound field, or sequence). +type Extraction struct { + Unsupported bool + Types []event.Type + TypesScoped bool + PIDs []uint64 + FileExact []string + FilePrefix []string + Ports []uint16 +} + +// TypePolicy is the in-kernel prefilter for one event type. DefaultAllow +// means userspace must see every event of that type. Otherwise an event +// must satisfy every required field, matching the union of allowed values. +type TypePolicy struct { + DefaultAllow bool + RequirePID bool + RequireFilename bool + RequirePort bool + PIDs []uint64 + FileExact []string + FilePrefix []string + Ports []uint16 +} + +// ApproverPlan is a platform-neutral description of per-type prefilters. +// It is derived from compiled filters and is not stored on RulesCompileResult, +// which remains a usage summary. +type ApproverPlan struct { + policies map[event.Type]TypePolicy +} + +// Sample is the subset of event fields the in-kernel approver can observe. +type Sample struct { + Type event.Type + PID uint64 + Filename string + Port uint16 + Truncated bool +} + +// AllowAllPlan returns a plan that never drops events. +func AllowAllPlan() *ApproverPlan { + return &ApproverPlan{policies: map[event.Type]TypePolicy{}} +} + +// PlanFromFilter builds a plan from a single compiled filter, typically the CLI +// expression supplied through SetFilter. +func PlanFromFilter(f Filter) *ApproverPlan { + if f == nil { + return AllowAllPlan() + } + return BuildApproverPlan([]Filter{f}) +} + +// BuildApproverPlan unions extractable predicates across filters. A type is +// default-allow when any applicable filter is unextractable, when no filter +// applies, or when the applicable filters do not share a required field. +func BuildApproverPlan(filters []Filter) *ApproverPlan { + plan := AllowAllPlan() + if len(filters) == 0 { + return plan + } + + byType := make(map[event.Type][]Extraction) + blocked := make(map[event.Type]bool) + + for _, f := range filters { + provider, ok := f.(ApproverProvider) + if !ok { + for _, typ := range event.All() { + blocked[typ] = true + } + continue + } + ex := provider.ApproverExtraction() + types := scopedTypes(ex) + if ex.Unsupported { + for _, typ := range types { + blocked[typ] = true + } + continue + } + for _, typ := range types { + byType[typ] = append(byType[typ], ex) + } + } + + for _, typ := range event.All() { + if blocked[typ] || len(byType[typ]) == 0 { + plan.policies[typ] = TypePolicy{DefaultAllow: true} + continue + } + plan.policies[typ] = policyFromClauses(byType[typ]) + } + return plan +} + +// Union combines plans by intersecting required fields and unioning their +// allowed values. Any default-allow policy wins, which is the safe direction. +func Union(plans ...*ApproverPlan) *ApproverPlan { + var out *ApproverPlan + for _, p := range plans { + if p == nil { + continue + } + if out == nil { + out = clonePlan(p) + continue + } + for _, typ := range event.All() { + out.policies[typ] = unionPolicy(out.Policy(typ), p.Policy(typ)) + } + } + if out == nil { + return AllowAllPlan() + } + return out +} + +// Policy returns the prefilter for an event type. Missing types default-allow. +func (p *ApproverPlan) Policy(t event.Type) TypePolicy { + if p == nil || p.policies == nil { + return TypePolicy{DefaultAllow: true} + } + pol, ok := p.policies[t] + if !ok { + return TypePolicy{DefaultAllow: true} + } + return pol +} + +// Allows reports whether the kernel prefilter would keep the sample. A true +// userspace match must always produce true here; false positives are allowed. +func (p *ApproverPlan) Allows(s Sample) bool { + if AlwaysAllowed(s.Type) { + return true + } + pol := p.Policy(s.Type) + if pol.DefaultAllow { + return true + } + if pol.RequirePID && !slices.Contains(pol.PIDs, s.PID) { + return false + } + if pol.RequireFilename && !s.Truncated && !matchFilename(pol, s.Filename) { + return false + } + if pol.RequirePort && !slices.Contains(pol.Ports, s.Port) { + return false + } + return true +} + +var _ ApproverProvider = (*filter)(nil) + +func (f *filter) ApproverExtraction() Extraction { + if f.seq != nil { + // Sequence matching is stateful: an early stage has to reach userspace + // for a later one to ever fire, so no stage can be prefiltered. Scope + // the block to the event names and categories in the filter's string + // fields, which is the same set rules.Engine indexes the sequence by, + // so the approver and the engine cannot disagree about which types can + // reach the rule. + ex := Extraction{Unsupported: true, TypesScoped: true} + ex.Types = typesFromStringFields(f.stringFields) + return ex + } + return extractFromExpr(f.expr) +} + +// typesFromStringFields mirrors the event name and category indexing performed +// by rules.Engine.Compile. +func typesFromStringFields(stringFields map[fields.Field][]string) []event.Type { + var types []event.Type + for _, name := range stringFields[fields.EvtName] { + types = append(types, event.NameToTypes(name)...) + } + for _, name := range stringFields[fields.EvtCategory] { + if !event.IsCategoryKnown(name) { + continue + } + cat := event.Category(name) + for _, typ := range event.All() { + if typ.Category() == cat { + types = append(types, typ) + } + } + } + return uniqueTypes(types) +} + +func extractFromExpr(root ql.Node) Extraction { + var ex Extraction + if root == nil { + ex.Unsupported = true + return ex + } + ql.WalkFunc(root, func(n ql.Node) { + switch node := n.(type) { + case *ql.NotExpr, *ql.Function: + ex.Unsupported = true + case *ql.BinaryExpr: + extractBinary(&ex, node) + } + }) + ex.Types = uniqueTypes(ex.Types) + ex.PIDs = uniqueUint64(ex.PIDs) + ex.FileExact = uniqueStrings(ex.FileExact) + ex.FilePrefix = uniqueStrings(ex.FilePrefix) + ex.Ports = uniqueUint16(ex.Ports) + return ex +} + +func extractBinary(ex *Extraction, expr *ql.BinaryExpr) { + switch expr.Op { + case ql.And: + return + case ql.Or: + ex.Unsupported = true + return + } + + lhs, ok := expr.LHS.(*ql.FieldLiteral) + if !ok { + ex.Unsupported = true + return + } + if _, ok := expr.RHS.(*ql.BoundFieldLiteral); ok { + ex.Unsupported = true + return + } + + switch lhs.Field { + case fields.EvtName: + extractEventNames(ex, expr) + case fields.EvtCategory: + extractCategories(ex, expr) + case fields.EvtPID, fields.PsPid: + extractPIDs(ex, expr) + case fields.FilePath: + extractFilenames(ex, expr) + case fields.NetDport: + extractPorts(ex, expr) + default: + // ps.name is deliberately absent. The only process name the kernel can + // read cheaply is the live task comm, while ps.name is snapshot state + // captured at execve. They diverge under prctl(PR_SET_NAME) and when + // the snapshot falls back to an executable basename longer than comm's + // 16 bytes, either of which would drop a matching event. + ex.Unsupported = true + } +} + +func extractEventNames(ex *Extraction, expr *ql.BinaryExpr) { + if expr.Op != ql.Eq && expr.Op != ql.In { + ex.Unsupported = true + return + } + names, ok := rhsStrings(expr.RHS) + if !ok { + ex.Unsupported = true + return + } + ex.TypesScoped = true + for _, name := range names { + typ := event.NameToType(name) + if typ == event.UnknownType { + continue + } + ex.Types = append(ex.Types, typ) + } +} + +func extractCategories(ex *Extraction, expr *ql.BinaryExpr) { + if expr.Op != ql.Eq && expr.Op != ql.In { + ex.Unsupported = true + return + } + names, ok := rhsStrings(expr.RHS) + if !ok { + ex.Unsupported = true + return + } + ex.TypesScoped = true + for _, name := range names { + if !event.IsCategoryKnown(name) { + continue + } + cat := event.Category(name) + for _, typ := range event.All() { + if typ.Category() == cat { + ex.Types = append(ex.Types, typ) + } + } + } +} + +func extractPIDs(ex *Extraction, expr *ql.BinaryExpr) { + if expr.Op != ql.Eq && expr.Op != ql.In { + ex.Unsupported = true + return + } + nums, ok := rhsUint64(expr.RHS) + if !ok { + ex.Unsupported = true + return + } + ex.PIDs = append(ex.PIDs, nums...) +} + +func extractFilenames(ex *Extraction, expr *ql.BinaryExpr) { + switch expr.Op { + case ql.Eq, ql.In: + names, ok := rhsStrings(expr.RHS) + if !ok { + ex.Unsupported = true + return + } + ex.FileExact = append(ex.FileExact, names...) + case ql.Startswith: + names, ok := rhsStrings(expr.RHS) + if !ok { + ex.Unsupported = true + return + } + for _, name := range names { + if name == "" { + continue + } + ex.FilePrefix = append(ex.FilePrefix, name) + } + default: + ex.Unsupported = true + } +} + +func extractPorts(ex *Extraction, expr *ql.BinaryExpr) { + if expr.Op != ql.Eq && expr.Op != ql.In { + ex.Unsupported = true + return + } + nums, ok := rhsUint64(expr.RHS) + if !ok { + ex.Unsupported = true + return + } + for _, n := range nums { + if n > 65535 { + ex.Unsupported = true + return + } + ex.Ports = append(ex.Ports, uint16(n)) + } +} + +// scopedTypes resolves which event types an extraction speaks for. An +// extraction that names no event type at all covers every type, which is right +// for a CLI filter because the source evaluates it against every event. Rules +// are not in that position: rules.Engine discards a rule without an event name +// or category, so the compiler keeps unscoped rules out of the plan entirely +// rather than letting their predicates constrain anything here. +func scopedTypes(ex Extraction) []event.Type { + if len(ex.Types) > 0 { + return uniqueTypes(ex.Types) + } + if ex.TypesScoped { + return nil + } + return event.All() +} + +func policyFromClauses(clauses []Extraction) TypePolicy { + reqPID, reqFile, reqPort := true, true, true + for _, c := range clauses { + if len(c.PIDs) == 0 { + reqPID = false + } + if len(c.FileExact)+len(c.FilePrefix) == 0 { + reqFile = false + } + if len(c.Ports) == 0 { + reqPort = false + } + } + if !reqPID && !reqFile && !reqPort { + return TypePolicy{DefaultAllow: true} + } + pol := TypePolicy{ + RequirePID: reqPID, + RequireFilename: reqFile, + RequirePort: reqPort, + } + for _, c := range clauses { + if reqPID { + pol.PIDs = append(pol.PIDs, c.PIDs...) + } + if reqFile { + pol.FileExact = append(pol.FileExact, c.FileExact...) + pol.FilePrefix = append(pol.FilePrefix, c.FilePrefix...) + } + if reqPort { + pol.Ports = append(pol.Ports, c.Ports...) + } + } + pol.PIDs = uniqueUint64(pol.PIDs) + pol.FileExact = uniqueStrings(pol.FileExact) + pol.FilePrefix = uniqueStrings(pol.FilePrefix) + pol.Ports = uniqueUint16(pol.Ports) + return pol +} + +func unionPolicy(a, b TypePolicy) TypePolicy { + if a.DefaultAllow || b.DefaultAllow { + return TypePolicy{DefaultAllow: true} + } + reqPID := a.RequirePID && b.RequirePID + reqFile := a.RequireFilename && b.RequireFilename + reqPort := a.RequirePort && b.RequirePort + if !reqPID && !reqFile && !reqPort { + return TypePolicy{DefaultAllow: true} + } + pol := TypePolicy{ + RequirePID: reqPID, + RequireFilename: reqFile, + RequirePort: reqPort, + } + if reqPID { + pol.PIDs = uniqueUint64(append(append([]uint64{}, a.PIDs...), b.PIDs...)) + } + if reqFile { + pol.FileExact = uniqueStrings(append(append([]string{}, a.FileExact...), b.FileExact...)) + pol.FilePrefix = uniqueStrings(append(append([]string{}, a.FilePrefix...), b.FilePrefix...)) + } + if reqPort { + pol.Ports = uniqueUint16(append(append([]uint16{}, a.Ports...), b.Ports...)) + } + return pol +} + +func clonePlan(p *ApproverPlan) *ApproverPlan { + out := AllowAllPlan() + for typ, pol := range p.policies { + out.policies[typ] = pol + } + return out +} + +func matchFilename(pol TypePolicy, path string) bool { + if slices.Contains(pol.FileExact, path) { + return true + } + for _, prefix := range pol.FilePrefix { + if strings.HasPrefix(path, prefix) { + return true + } + } + return false +} + +func rhsStrings(n ql.Node) ([]string, bool) { + switch v := n.(type) { + case *ql.StringLiteral: + return []string{v.Value}, true + case *ql.ListLiteral: + return v.Values, true + } + return nil, false +} + +func rhsUint64(n ql.Node) ([]uint64, bool) { + switch v := n.(type) { + case *ql.IntegerLiteral: + if v.Value < 0 { + return nil, false + } + return []uint64{uint64(v.Value)}, true + case *ql.UnsignedLiteral: + return []uint64{v.Value}, true + case *ql.StringLiteral: + n, err := strconv.ParseUint(v.Value, 10, 64) + if err != nil { + return nil, false + } + return []uint64{n}, true + case *ql.ListLiteral: + out := make([]uint64, 0, len(v.Values)) + for _, s := range v.Values { + n, err := strconv.ParseUint(s, 10, 64) + if err != nil { + return nil, false + } + out = append(out, n) + } + return out, true + } + return nil, false +} + +func uniqueTypes(in []event.Type) []event.Type { + return unique(in, func(a, b event.Type) bool { return a == b }) +} + +func uniqueUint64(in []uint64) []uint64 { + return unique(in, func(a, b uint64) bool { return a == b }) +} + +func uniqueUint16(in []uint16) []uint16 { + return unique(in, func(a, b uint16) bool { return a == b }) +} + +func uniqueStrings(in []string) []string { + return unique(in, func(a, b string) bool { return a == b }) +} + +func unique[T any](in []T, eq func(T, T) bool) []T { + if len(in) == 0 { + return nil + } + out := make([]T, 0, len(in)) + for _, v := range in { + if slices.ContainsFunc(out, func(e T) bool { return eq(e, v) }) { + continue + } + out = append(out, v) + } + return out +} diff --git a/pkg/filter/approver_fuzz_linux_test.go b/pkg/filter/approver_fuzz_linux_test.go new file mode 100644 index 000000000..910bd6b5a --- /dev/null +++ b/pkg/filter/approver_fuzz_linux_test.go @@ -0,0 +1,114 @@ +//go:build linux + +/* + * Copyright 2026 by Mostafa Moradian + * https://www.fibratus.io + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package filter + +import ( + "testing" + + "github.com/rabbitstack/fibratus/pkg/event" + "github.com/rabbitstack/fibratus/pkg/event/params" + pstypes "github.com/rabbitstack/fibratus/pkg/ps/types" + "github.com/stretchr/testify/require" +) + +// fuzzExprs mixes extractable shapes with shapes that must fall back to +// default-allow, so the property holds across both paths. +var fuzzExprs = []string{ + "evt.name = 'openat' and file.path startswith '/tmp'", + "evt.name = 'openat' and file.path = '/etc/passwd'", + "evt.name = 'openat' and file.path in ('/tmp/a', '/tmp/b') and ps.pid = 42", + "evt.name in ('openat', 'connect') and ps.pid in (1, 42)", + "evt.category = 'file' and file.path startswith '/var'", + "evt.name = 'connect' and net.dport in (80, 443)", + "evt.name = 'connect' and net.dport = 443 and ps.pid = 42", + "evt.name = 'kill' and ps.pid = 42", + "evt.name = 'openat' and file.path != '/tmp/x'", + "evt.name = 'openat' and not (file.path = '/tmp/x')", + "evt.name = 'openat' and (ps.pid = 1 or file.path = '/tmp/x')", + "evt.name = 'openat' and file.path matches '/tmp/*'", + "evt.name = 'openat' and ps.name = 'bash'", + "file.path startswith '/tmp'", + "ps.pid = 42", +} + +var fuzzTypes = []event.Type{ + event.Openat, event.Connect, event.Kill, event.Execve, event.Mmap, event.Accept, +} + +func fuzzEvent(typ event.Type, pid uint64, path string, port uint16) *event.Event { + evt := &event.Event{ + Type: typ, + Category: typ.Category(), + Name: typ.String(), + PID: pid, + PS: &pstypes.PS{PID: pid, Name: "fuzz", Exe: "/bin/fuzz"}, + Params: event.Params{}, + } + switch typ { + case event.Openat, event.Unlink, event.Rename: + evt.Params[params.FilePath] = &event.Param{Name: params.FilePath, Type: params.Path, Value: path} + case event.Connect: + evt.Params[params.NetDport] = &event.Param{Name: params.NetDport, Type: params.Port, Value: port} + case event.Accept: + evt.Params[params.NetSport] = &event.Param{Name: params.NetSport, Type: params.Port, Value: port} + } + return evt +} + +// FuzzApproverNoFalseNegatives is the core soundness property: whatever the +// userspace filter matches, the in-kernel prefilter must also keep. +func FuzzApproverNoFalseNegatives(f *testing.F) { + f.Add(0, 0, uint64(42), "/tmp/payload", uint16(443)) + f.Add(2, 1, uint64(1), "/var/tmp/x", uint16(80)) + f.Add(5, 3, uint64(0), "/etc/passwd", uint16(22)) + f.Add(8, 2, uint64(4242), "", uint16(0)) + + compiled := make([]Filter, len(fuzzExprs)) + plans := make([]*ApproverPlan, len(fuzzExprs)) + for i, expr := range fuzzExprs { + compiled[i] = mustCompileApprover(f, expr) + plans[i] = PlanFromFilter(compiled[i]) + } + + f.Fuzz(func(t *testing.T, exprIdx, typeIdx int, pid uint64, path string, port uint16) { + i := abs(exprIdx) % len(compiled) + typ := fuzzTypes[abs(typeIdx)%len(fuzzTypes)] + + evt := fuzzEvent(typ, pid, path, port) + if !compiled[i].Eval(evt) { + return + } + sample := Sample{Type: typ, PID: pid, Port: port} + if typ == event.Openat || typ == event.Unlink || typ == event.Rename { + sample.Filename = path + } + require.True(t, plans[i].Allows(sample), + "prefilter dropped a userspace match: expr=%q type=%s pid=%d path=%q port=%d", + fuzzExprs[i], typ, pid, path, port) + }) +} + +func abs(n int) int { + if n < 0 { + return -n - 1 + } + return n +} diff --git a/pkg/filter/approver_linux.go b/pkg/filter/approver_linux.go new file mode 100644 index 000000000..3d1f80037 --- /dev/null +++ b/pkg/filter/approver_linux.go @@ -0,0 +1,36 @@ +//go:build linux + +/* + * Copyright 2026 by Mostafa Moradian + * https://www.fibratus.io + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package filter + +import "github.com/rabbitstack/fibratus/pkg/event" + +// AlwaysAllowed reports event types the process snapshotter consumes. Dropping +// one in the kernel would desynchronize process identity from live tasks, so no +// prefilter is ever installed for them regardless of what the rules ask for. +// Mirrored by the leading check in event_approved in c/common/approvers.h. +func AlwaysAllowed(t event.Type) bool { + switch t { + case event.Execve, event.Exit, event.Clone, event.UnknownType: + return true + default: + return false + } +} diff --git a/pkg/filter/approver_linux_test.go b/pkg/filter/approver_linux_test.go new file mode 100644 index 000000000..8d60a95ea --- /dev/null +++ b/pkg/filter/approver_linux_test.go @@ -0,0 +1,140 @@ +/* + * Copyright 2026 by Mostafa Moradian + * https://www.fibratus.io + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package filter + +import ( + "testing" + + "github.com/rabbitstack/fibratus/pkg/config" + "github.com/rabbitstack/fibratus/pkg/event" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func compileApprover(t *testing.T, expr string) Filter { + t.Helper() + return mustCompileApprover(t, expr) +} + +func mustCompileApprover(tb testing.TB, expr string) Filter { + tb.Helper() + f := New(expr, &config.Config{ + EventSource: config.EventSourceConfig{ + EnableFileIOEvents: true, + EnableNetEvents: true, + EnableMemEvents: true, + }, + Filters: &config.Filters{}, + }) + require.NoError(tb, f.Compile(), expr) + return f +} + +func TestExtractEqualityListPrefix(t *testing.T) { + f := compileApprover(t, "evt.name = 'openat' and file.path startswith '/tmp' and ps.pid in (1, 42)") + ex := f.(ApproverProvider).ApproverExtraction() + require.False(t, ex.Unsupported) + assert.Equal(t, []event.Type{event.Openat}, ex.Types) + assert.ElementsMatch(t, []uint64{1, 42}, ex.PIDs) + assert.Equal(t, []string{"/tmp"}, ex.FilePrefix) +} + +func TestExtractPortList(t *testing.T) { + f := compileApprover(t, "evt.name = 'connect' and net.dport in (80, 443)") + ex := f.(ApproverProvider).ApproverExtraction() + require.False(t, ex.Unsupported) + assert.Equal(t, []uint16{80, 443}, ex.Ports) +} + +func TestExtractUnsupportedShapesDefaultAllow(t *testing.T) { + cases := []string{ + "evt.name = 'openat' and file.path != '/etc/passwd'", + "evt.name = 'openat' and not (file.path = '/etc/passwd')", + "evt.name = 'openat' and (ps.pid = 1 or file.path = '/tmp/x')", + "evt.name = 'openat' and file.path matches '/tmp/*'", + "evt.name = 'openat' and ps.pid > 1", + "evt.name = 'openat' and lower(file.path) = '/tmp/x'", + `sequence +|evt.name = 'execve'| +|evt.name = 'connect'|`, + } + for _, expr := range cases { + f := compileApprover(t, expr) + plan := PlanFromFilter(f) + assert.True(t, plan.Policy(event.Openat).DefaultAllow || plan.Policy(event.Connect).DefaultAllow || plan.Policy(event.Execve).DefaultAllow, expr) + } + + orPlan := PlanFromFilter(compileApprover(t, "evt.name = 'openat' and (ps.pid = 1 or file.path = '/tmp/x')")) + assert.True(t, orPlan.Policy(event.Openat).DefaultAllow) + + seqPlan := PlanFromFilter(compileApprover(t, `sequence +|evt.name = 'execve'| +|evt.name = 'connect'|`)) + assert.True(t, seqPlan.Policy(event.Execve).DefaultAllow) + assert.True(t, seqPlan.Policy(event.Connect).DefaultAllow) +} + +// ps.name is snapshot state while the kernel can only read the live task comm, +// so a process name predicate must never narrow the in-kernel prefilter. +func TestProcessNameIsNotExtractable(t *testing.T) { + plan := PlanFromFilter(compileApprover(t, "evt.name = 'openat' and ps.name = 'bash'")) + assert.True(t, plan.Policy(event.Openat).DefaultAllow) + + mixed := PlanFromFilter(compileApprover(t, "evt.name = 'openat' and ps.name = 'bash' and file.path startswith '/tmp'")) + assert.True(t, mixed.Policy(event.Openat).DefaultAllow) +} + +func TestBuildPlanIntersectsRequiredFields(t *testing.T) { + pid := compileApprover(t, "evt.name = 'openat' and ps.pid = 7") + path := compileApprover(t, "evt.name = 'openat' and file.path startswith '/tmp'") + mixed := BuildApproverPlan([]Filter{pid, path}) + assert.True(t, mixed.Policy(event.Openat).DefaultAllow, "different required fields cannot be ANDed across rules") + + a := compileApprover(t, "evt.name = 'openat' and file.path startswith '/tmp'") + b := compileApprover(t, "evt.name = 'openat' and file.path startswith '/var'") + union := BuildApproverPlan([]Filter{a, b}) + pol := union.Policy(event.Openat) + require.False(t, pol.DefaultAllow) + assert.True(t, pol.RequireFilename) + assert.ElementsMatch(t, []string{"/tmp", "/var"}, pol.FilePrefix) +} + +func TestAllowsNeverFalseNegative(t *testing.T) { + f := compileApprover(t, "evt.name = 'openat' and file.path startswith '/tmp' and ps.pid = 42") + plan := PlanFromFilter(f) + + keep := Sample{Type: event.Openat, PID: 42, Filename: "/tmp/payload"} + drop := Sample{Type: event.Openat, PID: 7, Filename: "/etc/passwd"} + assert.True(t, plan.Allows(keep)) + assert.False(t, plan.Allows(drop)) + assert.True(t, plan.Allows(Sample{Type: event.Openat, PID: 42, Filename: "/tmp", Truncated: true})) +} + +func TestUnionCLIAndRules(t *testing.T) { + rules := PlanFromFilter(compileApprover(t, "evt.name = 'connect' and net.dport in (80, 443)")) + cli := PlanFromFilter(compileApprover(t, "evt.name = 'connect' and net.dport = 443")) + combined := Union(rules, cli) + pol := combined.Policy(event.Connect) + require.False(t, pol.DefaultAllow) + assert.True(t, pol.RequirePort) + assert.ElementsMatch(t, []uint16{80, 443}, pol.Ports) + assert.True(t, combined.Allows(Sample{Type: event.Connect, Port: 80})) + assert.True(t, combined.Allows(Sample{Type: event.Connect, Port: 443})) + assert.False(t, combined.Allows(Sample{Type: event.Connect, Port: 22})) +} diff --git a/pkg/filter/approver_windows.go b/pkg/filter/approver_windows.go new file mode 100644 index 000000000..36f674911 --- /dev/null +++ b/pkg/filter/approver_windows.go @@ -0,0 +1,27 @@ +//go:build windows + +/* + * Copyright 2026 by Mostafa Moradian + * https://www.fibratus.io + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package filter + +import "github.com/rabbitstack/fibratus/pkg/event" + +// AlwaysAllowed has no Windows counterpart because the ETW source does its own +// approver work in internal/etw/approvers. +func AlwaysAllowed(event.Type) bool { return false } diff --git a/pkg/rules/compiler.go b/pkg/rules/compiler.go index 668e13078..151ec6000 100644 --- a/pkg/rules/compiler.go +++ b/pkg/rules/compiler.go @@ -61,6 +61,7 @@ type compiler struct { psnap ps.Snapshotter config *config.Config approvers config.Approvers + plan *filter.ApproverPlan } func newCompiler(psnap ps.Snapshotter, cfg *config.Config) *compiler { @@ -151,6 +152,7 @@ func (c *compiler) compile() (map[*config.FilterConfig]filter.Filter, *config.Ru } if len(filters) == 0 { + c.plan = filter.AllowAllPlan() return filters, nil, nil } @@ -159,9 +161,34 @@ func (c *compiler) compile() (map[*config.FilterConfig]filter.Filter, *config.Ru r.Approvers = c.approvers } + providers := make([]filter.Filter, 0, len(filters)) + for _, fltr := range filters { + if !isApproverScoped(fltr) { + continue + } + providers = append(providers, fltr) + } + c.plan = filter.BuildApproverPlan(providers) + return filters, r, nil } +func isApproverScoped(f filter.Filter) bool { + for name := range f.GetStringFields() { + if name == fields.EvtName || name == fields.EvtCategory { + return true + } + } + return false +} + +func (c *compiler) ApproverPlan() *filter.ApproverPlan { + if c == nil || c.plan == nil { + return filter.AllowAllPlan() + } + return c.plan +} + func (c *compiler) visitApproverPredicates(node ql.Node) { walk := func(n ql.Node) { expr, ok := n.(*ql.BinaryExpr) diff --git a/pkg/rules/compiler_linux_test.go b/pkg/rules/compiler_linux_test.go index fdb2ba7ce..351280417 100644 --- a/pkg/rules/compiler_linux_test.go +++ b/pkg/rules/compiler_linux_test.go @@ -26,6 +26,7 @@ import ( "testing" "github.com/rabbitstack/fibratus/pkg/config" + "github.com/rabbitstack/fibratus/pkg/event" "github.com/rabbitstack/fibratus/pkg/ps" "github.com/stretchr/testify/require" ) @@ -51,9 +52,35 @@ condition: evt.name = 'execve' and ps.name = 'bash' require.True(t, result.HasProcEvents) } +func TestCompilerExtractableApproverPlan(t *testing.T) { + rule := filepath.Join(t.TempDir(), "openat.yml") + require.NoError(t, os.WriteFile(rule, []byte(`name: Temporary file open +id: 7c1c2d3e-4f5a-6789-abcd-ef0123456789 +version: 1.0.0 +min-engine-version: 3.0.0 +condition: evt.name = 'openat' and file.path startswith '/tmp' +`), 0o600)) + + cfg := &config.Config{ + EventSource: config.EventSourceConfig{EnableFileIOEvents: true}, + Filters: &config.Filters{ + Rules: config.Rules{FromPaths: []string{rule}}, + }, + } + c := newCompiler(ps.NewSnapshotter(), cfg) + _, result, err := c.compile() + require.NoError(t, err) + require.NotNil(t, result) + pol := c.ApproverPlan().Policy(event.Openat) + require.False(t, pol.DefaultAllow) + require.True(t, pol.RequireFilename) + require.Equal(t, []string{"/tmp"}, pol.FilePrefix) +} + func TestCompilerShippedLinuxRules(t *testing.T) { cfg := newLinuxConfig(filepath.Join("..", "..", "rules", "linux", "*.yml")) - filters, result, err := newCompiler(ps.NewSnapshotter(), cfg).compile() + c := newCompiler(ps.NewSnapshotter(), cfg) + filters, result, err := c.compile() require.NoError(t, err) require.NotEmpty(t, filters) require.NotNil(t, result) @@ -66,6 +93,45 @@ func TestCompilerShippedLinuxRules(t *testing.T) { require.True(t, f.HasLabel(label), "%s is missing the %s label", f.Name, label) } } + + plan := c.ApproverPlan() + require.True(t, plan.Policy(event.Execve).DefaultAllow) + require.True(t, plan.Policy(event.Connect).DefaultAllow) + require.True(t, plan.Policy(event.Ptrace).DefaultAllow) + require.True(t, plan.Policy(event.Kill).DefaultAllow) +} + +// The approver scopes a sequence rule to the event names and categories in its +// string fields, on the assumption that the engine indexes the sequence by that +// same set and so never evaluates a stage against any other type. Pin it here: +// if indexing ever widens, the approver would under-block and drop events a +// sequence stage needs. +func TestEngineIndexesSequenceByStringFieldTypes(t *testing.T) { + rule := filepath.Join(t.TempDir(), "sequence.yml") + require.NoError(t, os.WriteFile(rule, []byte(`name: Execve then unscoped stage +id: 8e2f1a5b-3c4d-4e6f-8a9b-0c1d2e3f4a5b +version: 1.0.0 +min-engine-version: 3.0.0 +condition: > + sequence + maxspan 1m + |evt.name = 'execve'| + |ps.pid = 5| +`), 0o600)) + + cfg := newLinuxConfig(rule) + e := NewEngine(ps.NewSnapshotter(), cfg) + _, err := e.Compile() + require.NoError(t, err) + + require.Len(t, e.filters.types[event.Execve], 1, "sequence must be indexed under execve") + for _, typ := range event.All() { + if typ == event.Execve { + continue + } + require.Empty(t, e.filters.types[typ], "sequence must not be indexed under %s", typ) + } + require.Empty(t, e.filters.categories, "sequence names no category") } func TestCompilerSharedSemanticFixtures(t *testing.T) { diff --git a/pkg/rules/engine.go b/pkg/rules/engine.go index c5a20afcd..e1aef4f70 100644 --- a/pkg/rules/engine.go +++ b/pkg/rules/engine.go @@ -146,6 +146,16 @@ func NewEngine(psnap ps.Snapshotter, config *config.Config) *Engine { return e } +// ApproverPlan returns the conservative in-kernel prefilter derived from the +// compiled ruleset. RulesCompileResult stays a usage summary and is not used +// as predicate data. +func (e *Engine) ApproverPlan() *filter.ApproverPlan { + if e == nil || e.compiler == nil { + return filter.AllowAllPlan() + } + return e.compiler.ApproverPlan() +} + func (e *Engine) gcSequences() { for { <-e.scavenger.C From 7428156476f3adc0cf8d669833dc5a70700414c0 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian Date: Mon, 21 Sep 2026 16:05:36 +0200 Subject: [PATCH 2/5] feat(ebpf): Prefilter syscalls with versioned in-kernel maps --- internal/ebpf/approver.go | 257 ++++++++++++++++++++++++++++ internal/ebpf/bpf/clone_bpfeb.go | 78 +++++++-- internal/ebpf/bpf/clone_bpfeb.o | Bin 45224 -> 47720 bytes internal/ebpf/bpf/clone_bpfel.go | 78 +++++++-- internal/ebpf/bpf/clone_bpfel.o | Bin 44840 -> 47336 bytes internal/ebpf/bpf/ctl_bpfeb.go | 78 +++++++-- internal/ebpf/bpf/ctl_bpfeb.o | Bin 22168 -> 48016 bytes internal/ebpf/bpf/ctl_bpfel.go | 78 +++++++-- internal/ebpf/bpf/ctl_bpfel.o | Bin 21784 -> 47632 bytes internal/ebpf/bpf/execve_bpfeb.go | 78 +++++++-- internal/ebpf/bpf/execve_bpfeb.o | Bin 22792 -> 25296 bytes internal/ebpf/bpf/execve_bpfel.go | 78 +++++++-- internal/ebpf/bpf/execve_bpfel.o | Bin 22600 -> 25104 bytes internal/ebpf/bpf/exit_bpfeb.go | 78 +++++++-- internal/ebpf/bpf/exit_bpfeb.o | Bin 7904 -> 10432 bytes internal/ebpf/bpf/exit_bpfel.go | 78 +++++++-- internal/ebpf/bpf/exit_bpfel.o | Bin 7904 -> 10432 bytes internal/ebpf/bpf/file_bpfeb.go | 78 +++++++-- internal/ebpf/bpf/file_bpfeb.o | Bin 77944 -> 167576 bytes internal/ebpf/bpf/file_bpfel.go | 78 +++++++-- internal/ebpf/bpf/file_bpfel.o | Bin 77176 -> 166808 bytes internal/ebpf/bpf/mem_bpfeb.go | 78 +++++++-- internal/ebpf/bpf/mem_bpfeb.o | Bin 32248 -> 68248 bytes internal/ebpf/bpf/mem_bpfel.go | 78 +++++++-- internal/ebpf/bpf/mem_bpfel.o | Bin 31960 -> 67960 bytes internal/ebpf/bpf/net_bpfeb.go | 78 +++++++-- internal/ebpf/bpf/net_bpfeb.o | Bin 33632 -> 70208 bytes internal/ebpf/bpf/net_bpfel.go | 78 +++++++-- internal/ebpf/bpf/net_bpfel.o | Bin 33344 -> 69920 bytes internal/ebpf/bpf/prociter_bpfeb.go | 78 +++++++-- internal/ebpf/bpf/prociter_bpfeb.o | Bin 7160 -> 9696 bytes internal/ebpf/bpf/prociter_bpfel.go | 78 +++++++-- internal/ebpf/bpf/prociter_bpfel.o | Bin 7160 -> 9696 bytes internal/ebpf/c/common/approvers.h | 237 +++++++++++++++++++++++++ internal/ebpf/c/common/events.h | 24 +++ internal/ebpf/doc.go | 6 +- internal/ebpf/loader.go | 8 +- internal/ebpf/maps.go | 29 +++- 38 files changed, 1635 insertions(+), 174 deletions(-) create mode 100644 internal/ebpf/approver.go create mode 100644 internal/ebpf/c/common/approvers.h diff --git a/internal/ebpf/approver.go b/internal/ebpf/approver.go new file mode 100644 index 000000000..854494964 --- /dev/null +++ b/internal/ebpf/approver.go @@ -0,0 +1,257 @@ +//go:build linux + +/* + * Copyright 2026 by Mostafa Moradian + * https://www.fibratus.io + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ebpf + +import ( + "fmt" + + "github.com/cilium/ebpf" + "github.com/rabbitstack/fibratus/internal/ebpf/bpf" + "github.com/rabbitstack/fibratus/pkg/event" + "github.com/rabbitstack/fibratus/pkg/filter" +) + +func (l *loader) populateApprovers(plan *filter.ApproverPlan) error { + if l == nil || l.exec == nil { + return fmt.Errorf("approver maps are not loaded") + } + if plan == nil { + plan = filter.AllowAllPlan() + } + + cur, err := l.approverGen() + if err != nil { + return err + } + inactive := uint32(1) - cur + if err := l.clearGeneration(inactive); err != nil { + return fmt.Errorf("clearing inactive approver generation: %w", err) + } + if err := l.writePlan(inactive, plan); err != nil { + return err + } + // The retired generation is left populated on purpose. A program that read + // the old generation before the flip still resolves its lookups against it; + // wiping it here would turn those in-flight events into drops. The next + // reload clears it before reusing it. + if err := l.exec.ApproverGen.Put(uint32(0), inactive); err != nil { + return fmt.Errorf("flipping approver generation: %w", err) + } + return nil +} + +func (l *loader) approverGen() (uint32, error) { + var key, gen uint32 + if err := l.exec.ApproverGen.Lookup(&key, &gen); err != nil { + return 0, fmt.Errorf("reading approver generation: %w", err) + } + return gen & 1, nil +} + +func (l *loader) approverRejects() uint64 { + var key uint32 + var n uint64 + if l.exec == nil || l.exec.ApproverReject == nil { + return 0 + } + _ = l.exec.ApproverReject.Lookup(&key, &n) + return n +} + +func (l *loader) writePlan(gen uint32, plan *filter.ApproverPlan) error { + for i := uint32(0); i < approverTypeMax; i++ { + key := gen*approverTypeMax + i + typ := event.Type(i) + pol := plan.Policy(typ) + mode := policyMode(pol, typ) + if err := l.exec.ApproverMode.Put(&key, &mode); err != nil { + return fmt.Errorf("writing approver mode for type %d: %w", i, err) + } + if mode == 0 { + continue + } + if err := l.writePolicy(gen, typ, pol); err != nil { + return err + } + } + return nil +} + +func policyMode(pol filter.TypePolicy, typ event.Type) uint8 { + if filter.AlwaysAllowed(typ) || !typ.Exists() || pol.DefaultAllow { + return 0 + } + var mode uint8 + if pol.RequirePID { + mode |= approverReqPID + } + if pol.RequireFilename { + mode |= approverReqFile + } + // The kernel only parses a destination port out of the stashed sockaddr for + // connect. Enforcing a port on any other type would compare against zero and + // drop everything, so those types keep the rest of their policy instead. + if pol.RequirePort && typ == event.Connect { + mode |= approverReqPort + } + return mode +} + +func (l *loader) writePolicy(gen uint32, typ event.Type, pol filter.TypePolicy) error { + id := uint32(typ) + present := uint8(1) + if pol.RequirePID { + for _, pid := range pol.PIDs { + key := bpf.ExecveApproverPidKey{Gen: gen, Type: id, Pid: pid} + if err := l.exec.ApproverPid.Put(&key, &present); err != nil { + return fmt.Errorf("writing pid approver: %w", err) + } + } + } + if pol.RequirePort && typ == event.Connect { + for _, port := range pol.Ports { + key := bpf.ExecveApproverPortKey{Gen: gen, Type: id, Port: port} + if err := l.exec.ApproverPort.Put(&key, &present); err != nil { + return fmt.Errorf("writing port approver: %w", err) + } + } + } + if pol.RequireFilename { + for _, path := range pol.FileExact { + key := bpf.ExecveApproverFileKey{Gen: gen, Type: id} + copy(key.Path[:], path) + if err := l.exec.ApproverFileEq.Put(&key, &present); err != nil { + return fmt.Errorf("writing file approver: %w", err) + } + } + pre := l.prefixMap(gen) + if pre == nil { + return fmt.Errorf("missing filename prefix map for generation %d", gen) + } + for _, prefix := range pol.FilePrefix { + if prefix == "" || len(prefix) > len(bpf.ExecveApproverLpmKey{}.Path) { + continue + } + key := bpf.ExecveApproverLpmKey{Prefixlen: uint32(len(prefix) * 8)} + copy(key.Path[:], prefix) + if err := pre.Put(&key, &present); err != nil { + return fmt.Errorf("writing file prefix approver: %w", err) + } + } + } + return nil +} + +func (l *loader) prefixMap(gen uint32) *ebpf.Map { + if gen == 0 { + return l.exec.ApproverFilePre0 + } + return l.exec.ApproverFilePre1 +} + +func (l *loader) clearGeneration(gen uint32) error { + if err := deleteHashGen(l.exec.ApproverPid, gen, func(k bpf.ExecveApproverPidKey) uint32 { return k.Gen }); err != nil { + return err + } + if err := deleteHashGen(l.exec.ApproverPort, gen, func(k bpf.ExecveApproverPortKey) uint32 { return k.Gen }); err != nil { + return err + } + if err := deleteHashGen(l.exec.ApproverFileEq, gen, func(k bpf.ExecveApproverFileKey) uint32 { return k.Gen }); err != nil { + return err + } + if err := deleteAll(l.prefixMap(gen)); err != nil { + return err + } + for i := uint32(0); i < approverTypeMax; i++ { + key := gen*approverTypeMax + i + var mode uint8 + if err := l.exec.ApproverMode.Put(&key, &mode); err != nil { + return err + } + } + return nil +} + +func deleteHashGen[K any](m *ebpf.Map, gen uint32, genOf func(K) uint32) error { + if m == nil { + return fmt.Errorf("missing approver map") + } + var key K + var val uint8 + stale := make([]K, 0) + iter := m.Iterate() + for iter.Next(&key, &val) { + if genOf(key) == gen { + stale = append(stale, key) + } + } + if err := iter.Err(); err != nil { + return err + } + for i := range stale { + if err := m.Delete(&stale[i]); err != nil { + return err + } + } + return nil +} + +func deleteAll(m *ebpf.Map) error { + if m == nil { + return fmt.Errorf("missing approver map") + } + var key bpf.ExecveApproverLpmKey + var val uint8 + stale := make([]bpf.ExecveApproverLpmKey, 0) + iter := m.Iterate() + for iter.Next(&key, &val) { + stale = append(stale, key) + } + if err := iter.Err(); err != nil { + return err + } + for i := range stale { + if err := m.Delete(&stale[i]); err != nil { + return err + } + } + return nil +} + +func sharedMaps(exec *bpf.ExecveObjects) map[string]*ebpf.Map { + return map[string]*ebpf.Map{ + eventsMapName: exec.Events, + dropCountMapName: exec.DropCount, + scratchMapName: exec.Scratch, + scratchHeapMapName: exec.ScratchHeap, + enabledMapName: exec.Enabled, + approverGenMapName: exec.ApproverGen, + approverModeMapName: exec.ApproverMode, + approverPIDMapName: exec.ApproverPid, + approverPortMapName: exec.ApproverPort, + approverFileEqMapName: exec.ApproverFileEq, + approverFilePre0Name: exec.ApproverFilePre0, + approverFilePre1Name: exec.ApproverFilePre1, + approverFileHeapName: exec.ApproverFileHeap, + approverLPMHeapName: exec.ApproverLpmHeap, + approverRejectMapName: exec.ApproverReject, + } +} diff --git a/internal/ebpf/bpf/clone_bpfeb.go b/internal/ebpf/bpf/clone_bpfeb.go index e8366cd2a..d3d15e461 100644 --- a/internal/ebpf/bpf/clone_bpfeb.go +++ b/internal/ebpf/bpf/clone_bpfeb.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type CloneApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type CloneApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type CloneApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type CloneApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type CloneScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -83,11 +111,21 @@ type CloneProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type CloneMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // CloneVariableSpecs contains global variables before they are loaded into the kernel. @@ -116,15 +154,35 @@ func (o *CloneObjects) Close() error { // // It can be passed to LoadCloneObjects or ebpf.CollectionSpec.LoadAndAssign. type CloneMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *CloneMaps) Close() error { return _CloneClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/clone_bpfeb.o b/internal/ebpf/bpf/clone_bpfeb.o index b8237d893fc6f55307b3ed0e75706f9b5ac4c440..34882e98cb706c0330e9cc3869096e4749310e95 100644 GIT binary patch literal 47720 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 diff --git a/internal/ebpf/bpf/ctl_bpfeb.go b/internal/ebpf/bpf/ctl_bpfeb.go index 16ff6f0b1..4ca490886 100644 --- a/internal/ebpf/bpf/ctl_bpfeb.go +++ b/internal/ebpf/bpf/ctl_bpfeb.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type CtlApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type CtlApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type CtlApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type CtlApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type CtlScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -75,11 +103,21 @@ type CtlProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type CtlMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // CtlVariableSpecs contains global variables before they are loaded into the kernel. @@ -108,15 +146,35 @@ func (o *CtlObjects) Close() error { // // It can be passed to LoadCtlObjects or ebpf.CollectionSpec.LoadAndAssign. type CtlMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *CtlMaps) Close() error { return _CtlClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/ctl_bpfeb.o b/internal/ebpf/bpf/ctl_bpfeb.o index 63c85584abdebe8666b8ed7c18b95adafcb63e7a..769b9f2c6ff59b42f63a784d912f2d46b82eb699 100644 GIT binary patch literal 48016 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 diff --git a/internal/ebpf/bpf/ctl_bpfel.go b/internal/ebpf/bpf/ctl_bpfel.go index dc85991c4..74590e969 100644 --- a/internal/ebpf/bpf/ctl_bpfel.go +++ b/internal/ebpf/bpf/ctl_bpfel.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type CtlApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type CtlApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type CtlApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type CtlApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type CtlScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -75,11 +103,21 @@ type CtlProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type CtlMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // CtlVariableSpecs contains global variables before they are loaded into the kernel. @@ -108,15 +146,35 @@ func (o *CtlObjects) Close() error { // // It can be passed to LoadCtlObjects or ebpf.CollectionSpec.LoadAndAssign. type CtlMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *CtlMaps) Close() error { return _CtlClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/ctl_bpfel.o b/internal/ebpf/bpf/ctl_bpfel.o index 84c760c08400ce81aa939c234f98691cd147777b..23b8cbee96b4dfdb371c8b252da95e80e1f68c69 100644 GIT binary patch literal 47632 zcmeI5e{fvab>A)2~Izu<>i~=JH+pZi<12@XdCecLjLDoK+;N`#)CV2`@Nt0>)m_zp7VZU`Q?L$A53l7U?glXKQ=2Q zsm9d)a3vnuXk@OXlBc)3^se@oHgoLs2RdxRtJFxEV(0S~&2`s1J^!N9&6L0N&O7hC znlgrKe3iB@&~|!m=^ZXH^-Rrbq2qRQj<~Di4s)N?4W>ZaW@haEct0WW)$WJub-zo! z)8BIYzg$1Le(-MfUqt_JT(JGWl6I&Wa~e z(wCt>f;OOULzkd$LF>>9&_(E*&>Hj&D1STD@6zkgD)cqzJoFW41^O~{4*C+b3}vh1 zc4wi_Lrc)J&}rxyXc77>bP_raO`s#tA?P492R#byhaQ1up@*S;&;!s2dM~sWx)+*( z?u4eHw?ISaP0()W4bT9(71{ya1hrzOUT8Q!hV_(x;VsMg7cM%#;MwQJHSDv?kO5PO zu|A(5<%M?s>o(aOBWR=OL!{iJ{Ef?(w7J@WaNZm5TK?!f?~KCvoE6ix;b=?${C@GwbfrFR z^QX2{ZGX6b9P&3_-8`R1|GU~BvF$a-xgFo@jB8i>(eqEb^skcet{*pd+4}x?*ZzK^ z=Ki>)d|;a)y~s$q4E+(b0eu^~1bquyhhBg#Lf?eepl?7Ipsz!#(AS{z&{v=p=*!SK z=u6Nt^c-{+`aHA*Jqw+No`Dvj&q61maXEg#3N?Z$Cy`*Gab zk2r4aPaL=QJB~xU-+bWe#c}I66*X+CiE;`k`?`;qT7AGmsPJc#@p@}1@bS1*o7kUxZcr}@Cu zi{o+RC&+i24_v)Ceir$Y$ak6#T)j9xgZv`$o#q2qFOJV5e;WBt^MR`u$Im0bgnXy@ zz}1W6bI6}XzSDf*>c#O($S)(`X+CiE;`n9c&mrGwK5+Ho_!Z<=knc1fxO#E?8uI6n z?=&B{dU5i}~o#q2qFOJ_r zejWKv^MR`u$8RHl3HeU*fvXqCKSF*3`A+kJs~5)?k-v<5r}@Cui({NO!tcj%tN-un z9NNScFFEe;!H0MZMimc%qshlkn-hx`bw|AxL)_W)I0qXT-O9^w&RZ1t6k^t zxcGX|`olHbnRn+qFH#{2t6f)eI~|nYybi&2=4$(wd6Ry~bs@LI=Qme>9daXgkIvQ3 zH;?xrvFzt+z8{{~pLiVJ_2O1)=jzAt%QOQ#j(=vyv2xz{k{g%3s-kwE`3bM164*lm zJ4j$Z3G60;y(O@-1ooN0E)!>$`J~R>H2DPfpDco%-RF}U_zma+^mS+z`Wkc|`UXbyT5+7CSf%|Z`D`=AG) z5%gYYFLW<71KkNtLvMkG(3_y$&>NrubStz2x(RB9?gQaE3hOEV46dV|xw`ZF=5-X- z=M$v7kk7M|q2OOfIs3la>!^QZJHBEMXD$2JE4)AdI?C+_*HL0G|Ie!=Ak-IpHEF1e06?B?&At~}qzTKhWc@#g-x#`<+s(N3J4 zN9F_g51e=A1NaY|r{)9r51iNLgB0@E^e~s24)vKLYrV0RAI@{|Mke0{D->E(3SoKuPP@QEvX%ucOXlJxyDU zW2fuaQLke@-o*UWz)pW=uA?@8X(JEp^4C#kZMin{tksp{d7nGJtUo7k>!ehMo`cRp zpNE#9u)7lMt#k(IMd-88N$5BNrubStz2x(RCKZ_#st&9>t!_Rwb8KabSsw>kM;9g%!l(c>(2?`@7JFb*mbe~oZwB^M-B7g^k?S$w)21TVeSgfZ`lgTdvIr1vvMT{_O=^?h&tyNgNMUbRPC_a4zdp!#xu>+yDXAK~iX zhtJ#nwweEC=V59lvGYGQGX%{+`=MEAA2fpYLNm}bG=z3T184`-y)ZpBvuyh@HPe7D zLF>>(XbrjmtwQIa73dta44s9RpwrMIbP}3ChoCuVKQs&NgGSI^Xa<^whR|+k0PTPp z=(1f`G=At3v<_W_y6fPnnFVkaIuETt=b&ZiEVKljh8Cfd&;&XJ%|ZL2S!f?Lg7!i) z&@?oJc0&Vb2h@svFOFYGnrg>>CR}@`Uv&3>r?$IxPrq1m>vVf)E9Reb*EvnQc4lv; zW+IzEH6#6S{rxJX@_QWT@m>itdy=UM*Pky^dPtm~u(!)izTG_^koV*B?QR_BV=6>} z-(MRdW&7ljaeJa4qqyvc`^O_VKSm!EuJrw}=6ihGv$h_$!|h*nJHO@L@9Ns<#>wsQ z2-oTd=ks{@m75sv6Xv(`-dFy<=(-PBG^@Ushw(}~r|~{p*XHloif!gktUBv(ZSm)M z>mB^}CB@&n_gyaa_wIY*adGhdy?bv5{{ES(_4m#pOS@O^?_ah3X*2unx_uSvPLKDB z{kyz(^iA9BW&d8R%ltO>-{b6N0{(ph{(S=eeFFY{0{(ph{(S=eeFFY{0{(ph{(S=e zeFFY{0{(ph{(S=eePY>uGgA`{=n}LJU4+)43(zWb9$JCULCertXbCzEEkY-u33LdW zgZ4wS&^~Ac?S*EbX=n)Th6d0MsDUoq?}5e-U4qu3i_jW$0a}I5Lo3iZXc;;SEkUQD zMd&0nfet})(0*tZ+6RrGz0eFa4Gp2)&;Z&2wQ{L{f6ldk`bBr&V`_V33(EQ2)ONSO z%lUt{OaA-E{PvaOfVKDLalrMH{m;7JcYgbC*6+I;bNs#W3b~Tw*t;KxR{TAm&#!eH z;`*{5IS#EH&)m9|<2n0b4qWaGZO(fe^Xr^Q!CASB^XKZvDRB#s7!LC4XP5$9u)csTbV&hX1^Lt-mAeGXEa?KWg{CejS42)C`VOGdNDo^tp4{aGaXKacahWqf;|DPR-yrHG|{S%rbxdbpG6cE0?Xg@Ry?Sn?pUT6lIhKA5?XaMbiTDkN%h3k;1 z=UjXG`h)!#|J}WR{IPc2JpM#zU;5$tyM8=!^Um}4H+wva;CF7fs{P&S{@tCoT#bKs z&z*kK`%drGzu$^+R{n|?kk?rNK(aiwi!-QWNJ;_ts=&oA4|Nvj7=#UtUvhmPFwQ1-C< z#@0W7mS^Cf{?`rm@1=Q+XXsH5Z~ux7)`b*5Ua=?8Bz#^HHqqE8FMN5(=^vu4jW!BW z&XF-G{7E2lOC2uDiPXj>KKuNjB#{0bZQNc&+ikQ_*v7XC(HG{_7XEahrCnUIa!!iR zJrP>U`0en0kRDg4gYT-|i8%M^6E1$qnE0yQc}mm4KMe+B>ENsI$54kYJaTcKqfH^j zd5n0ZWyi=*&m!6iwDGhTX&a`EAKz7JJ4qXbZC&)?_t~Ab+q{->N!yf@a(}UXX&HN? z!6us&-z9p6HmbLY?_^F>9IpzQuOS|h{u<&%(r+MMB|V2YckY`M=edk1{xae@idQHe z(pIGSwhCX&Hb`3b7p|nIc+4F9earXE`~Ew$MYQQPw1d*Bv@Ov_VH?|#?0dDgRvQPe%_?mT z+9+(>NgvV{MN@ZhstYaSh>*D2{&rD5mszdv_T-rMm!UHL{`L?fwCv9<4x5u=JHCc0 zQ32~;ZlXA^PY%33I3Dsw>AdD6+Bo=q<@w;i^Sqn3h&Jx)UfPPZ@tTr(zJ=PMux%fG zxTxjS-6TDf!0oa>TCE=sP?>uuKcbE8hvQk=+#L15~{~~R?CLW@#N}G&__xl=c6t*3r4;Qt^wfEd^4efr~YuBIi zkMUk9tmT_{{;RaTg|;51xb*RA+mf;W7;QbeN?VVRVHt<=sf_h43b*<#@WB;%4{2?I1k|4#B{Dk|LmAp>=QGZ z*>`Z@A@cW6flqbGk(?Me0|WaXdu;#b2R?h~7Y_~``F!@^zMqQel#A>4-L4Cc=TAt&_@q{?B=BbhR*q9j~J#``P|Xfl2Ah0zo7$Q^|zlc(;;-;p05*+sEkd0tiF{n-Zx zvX4FbP+B#!GaRGuG(R3D;{&6GV`JfM{JGOEm2k8$zQc45KNY5L=F}Yqh0JJA#*Frw z!AUbVYzBwT$+cUmT|88K#E^cZ5?WbI;y2D-I4*oy0!E>#gB!Cr?n4 zoo3D_Be&*}wuN`BHifck#&{OV1%%HOMo&@?GSpUKGN!L|mEK6j0lO-By-~-wGIz}O z!d9nmeqi9qQ^OftOW@rHg4nAu!mY>-@+zLO>*LG;la-x zaZdK({r%z3hdkvdcGw5IRBN_qkeaC8jeDKiWgSM00ocp$Imu>X+`&6fq+R|;VxOO+-Xm^HKP1JdE zg_r#T#9eyJ*AAM}-Lzi1fGMkG`EpVI;_MD@zmMFubL_NlUKu?2NA^E_aDapsORp{2 zVio!1bebBWs&weU00eXkZbv*FG(YH}?eG=M4j)i@$Sre!$+h(~7dJb0?Knq!-LAeA z7DmPj;T3)X_LzlT@K?;$E?u&ZK6b=)olSNZA8u)`Sa@!1npzSz?UDs?^V(zP2I*_% zy1X*&Ny=r{gF9GKHLgY7;Q`!it5OqeTD;HE;Sn~;hIldRn)7%(S(NL_QA^am zt?KsXl3i`=Us}+;$kQ1Jee1X1$C2jO4z}ORcs%wrH;*G4;{f8f?a<9}E`Lp4DZ?E# ze3C|I*K{sBT8Kvml9(N}IW~HdP76i~@nB)pW#mWcO!&kYoe58#HnbM#ME1#(C&zge z81AC6=h2ya?y@VPwE*?9)&98`d`joH!fVLweU;)~|76{}@?53*ctLz zxfTy&t@b%zTDNg_G1NF;VNgAmPZ&EF^!*t-fgCAt>}iS(jPq5Caj~Ztf!idH3czc6xbk}LyN;eAVn%vw@O4oxnJWii{4bEv7 zk@!i9KS5g?T~Km)=3l3+J?F~$`4Q!Rm-2o{Tj%SW>^(%E`Mv>{{~%pur$&q^qdbWX zbM(pOcT#@m;wDp5TnCfbutc9+{xe+u?M;T?r1F{HAz_~2e0r*r2BW&ksQj$roGL#A z{!MQ0hBkYDgxeP`tMYu0kMsYS%5N^F>^&6b|3bX=Ov>=RG=Dz$O>NGXz;AFf%Y5*2 z5}zZml;=0aIbY@@r-e8k+{9D&D4nb&zkS1t)2dC ztPYm`EP?qKz_yGKP(3dH6)vBoOb7T^iBpp))7|FsUn9QphK(i-t`mQ#d!xyK+eq7K zfkt52A9cyLe?4gjO=b>!fV7S1@gz7Vec!zs&9uiMamnLrh|6Hv z{~Va>b@pvERWR$;!yCjm1ph}a-@nl;dE8FC4E{0cwK@J0+<31c-FkGR z3BVsF-9~?Y-|g`Z;?U!*#2K*kzZZO%v}0(a$$7k)cnJLWNZThjn#AL+#6^!ee->=l z2Q98Su;Zg^wEbmTPvCz}dfh82vjnb^ZllH70KZAPnHFb2cdvMT35VcL z(#~qiMBx3Tn_o}a|JjDi^Z#hGX(46$>82|4Y2xeOp!Ea(EzYOKo}(LOod1`^9dFWl z0yl^|7gJ_h@jNlxkAx~%?0HFX11$E-4+#AFd^6Lx?~LMJu=u+^RX?lpClwdL;?GK| z{;bNMSG=Ig*T6gJz|om*GfRs3p|?N204)9}4HkdYugd4ZGM`1oB~^YFEb~)QTvO#2 z!P1`wSo*^UOYXn;#}4pC_{VNyUN7Pw(_mQ-8L;@rKCt-5ELi+wj&90xd*UAxu=vMG zu=vMmu>oq0_{WUL>>ner_{To5_{V;*_{W^b>>r0bX8$+|mi`yP;veTcX8%|Li+`N= znEm5|$Lt^LVDXO)ui&4lMq0?naj{{;>iU|5#I8C-&`U2`u)rjPhbX9rRKI?_WXy7W+wq#eOni zv7d-uXyE!{KUuKYPd`}fX9z6&OTc13(_pcm5?JhK)?>DxGFa@V;xXILyvJ-m3t-uQ z4J`Jv1Qz>gc+B>*>@nL9Km6qJi~R&1v;Bl%v7aBJ)ei~r0pJlMv55GXk z_9gZcD$an#ezIV(pBz~1XK1HuPwXcFi~S@SmoN4+2^RaARXhiNxPz`Q=;C!jaSi-6 z%5N{xdhmEF@sh`!zYP8zDu3-cS`YMKpT~cmd6urvz~3d_`aJntu*`QF{GTbmqfFnw z$D4_>U~6A=^B||{4}rTo>3aLZ22%t-Lfl^8U`oXP`Su+6mpGrU&lbU7V}2=R>R`LS z19ZKm>Mw(5d4E~D{@U%@xBEMiG9mcSDL?f}%FOO{`Tw2x2D)A=d;EUlIdIn&YLASx z0=|{`Oq;2K?;_q>r27xxL&U+eZKe)>ip$f*{1W(!%yjYI08bNN^L(3GR{8t_F3-ip=zV1!BKLP#$aVM>p5d2r1e<5Yk;P=zJ6rFFSOa}aMX1W>D3%-~5{cqFt zsK=eeePEfde((`0pK8$cCipqxk95=ZwJKi*e`G7IyPL@WDW3QE2FkCi`b*%?Q~hf~ zTF;6Ny_}7T9O>Z>4iX)G&q5K^9kEnd-PP$*9cpChDZa+igBWC*% z`Nz|^zsewPwX=Qi+y&3#Xd70vwcQjvCpik-wzi1 zOu%BF)5JW#VvqA+vBxS{?6C%x{w;#V9vfh>M?)`Qa{IErChu`9_E_|o?Qt3`_EQ2k z==<4nw#}5mO?w45?G-Hcx(F6~T>^`}Ho#5$1dBcLi>TaxvBv-`_Sg*;dkn#1k7=;j zBR#XS?TJ0obJZrZJw{-euPj*XF$WfVEUEIdV6n$J#TAd)9v4;pI#}$np?DcA_Sj7? z=kolBJ!Ta5dd&9N4;FizR9pm$Jd;suYlQ2vs~T)qJw;rhLFeEg*A zuW;b;7Rv7i&rtc)xi*s_Zh787?E8nD;vum3he?mwKNLM?|4;&pe<*{+Kg@x}Kg@&0 z{;FW{4~rhNe^>&Ge^^%a`9Ess@rZxu28(~l5c~ci2NwS@1Q!1=36}m9!Qvlg!Qvn0 zz_Q-M{ceBaAJQJPf5?Ev{(He<{}EX1zaK32KLi&0Pr%}DCc)wliYk8^EdF5@EdHSk z7XL5@7XMHIi+`90i+`ws#Xl@~%>JPUmielK#XmH_;vd5M-F!;~R?^_Q*ex@7rSp7JKXii#_&( zrGGiF*yAKv>~R__>%~0OYL6Wrvpoi2v7c_R9Ir#L*lPydv{!J`UcpU!1vl*#EcQ7G z7JHlqi#?XWVvn<6vBxr4>~Rh(_E-UnJw#R-|KL-|jOcYOo#U5wDVviNY^B%K3E`r7WmKB>rZaiX-0WCCsmLHOK)Al*q z{v9!gB5lmntPS(vhr!F>QE;@umH!5K2`u$PYM0xS`m=P*_S>(4CBK`V1#!N#p94$# zbKrCb6{65f&tClY60p>tq-&LaD)%8eH|0D~58pyNd~d=JpF%qOSwDOq>3pr?hp!`@{iYxO2sT}<$NH5yeD=_M{iA+(>yTp;Ck zDqu;(k91jfzl-#YO1}Z^G}L}SgY>FuKSnx=H{H`m zkscr;gz`Ih?=vgTR^0lZpnOJ^|2opMDxKe@cZ)bM^HNT4W^&9+kKg^_!1V!nfu4@j&Km> zcRhr;eSQ~1nES`?MhJ8N_+0~G?jOGkAk6jo*}gFMFY%cB$Isq5H2e3V73TWMhgX>Q z&(D@QaCzQ8Kda@y%=_nOsT`QOK0h1fz|8y4dd&OhXO|o}pXZ04HFA*p{aBdHynlW+ z$AOvm-v|H4%=_nOQ5>Ycxow4c|Gggb{`uJt2QJV1m*XpQL|Ynuj(Ii)N*Nx+%wAb%3x5xK(IdDF=$M#`;+o>R;)Y_AY8_voI8>Zb94XE! z&MD^OG6$KzqT-U`vf_&3s^XgBy5fdnImMCw1RGoX7b?yujudAV=M*Q3i;7E%%Ze+C ztBPxi>xvtS?HA#F9|2E<$D!hk;z)5;aZYifxTv_KxU9IMxT?6OxURUNSWd|}nN1_W z`H^s_IHNdHoK>7toG30TE-5Z6t|+c5t|_i7ZYZWxWE*6>f#OhcMscJ#t2n1PQCw79 zQe0MCQCwAAQ(RZvP;78M+Z?~*P;o|aq&TZMr#MkuR9sSAR$NhBRa{eCSKLr+|CotZ zKy&;Zt?MCFoKYMp&MM9+P81gvmlT&3R}@zj*A&+kHx%;^$Z%+mUva27qc~EWRm^`o z;kTbCE-Ef5E-S7mt}3o6t}AXRHs1ND^?!;(#Tmts;;iDF;zV&#aY=DmaYb=eaZPbu zaYHfw`>d7k-#g#s`3Mzf6#M7fTt2JvbBg`*Yc5|@`6b0=#TCU>#Wlrs#SO*wKOduh zG}k|#8wiJrGm0a{S;aZUiQ=N-lH#)BisGu`n&P_RhGP4pKmPb}KchK*#rUnH=6ppe zKdU&WI8j_wTvA+CTv1$ATvJ?E+)&JaTg5@f8z>GHXB0<@vx@n7mfwD&xTv_KxU9IM zxT?6OxURUN*!=>OH-6l&lKBV~XB0<@vx;+y`FWi`A4SC_#bw16#Z|>M#dXCE#d70P z#v25!{R#`;+o>R;)Y_nDcjQDKyj!zqc~EW zRh(0tC@v~4DK0CnD6T55DXuGSD5jhIt>af5D$Xd56lWFZ6eo&{ic5;iiYtn%iffAN ziW`az?kCH7=D)q;ARH>@zqRx8BgI+8ImLBRd1=3>@=J=#iYtn%iffANiW`beSL=8J#i8Pi;z)5;aZYif zxTv_KxU9IMxT?6OxURUN*lbthR~#zND2^0o73UNuii?U%ipz>CimQriitCCSip>Yq z_!WnWGm0a{S;aZUiQ=N-lH#)BisGu`n&P_RhGO~gd9lZ!yLCQ7#Tmts;;iDF;zV&# zaY=DmaYb=eaZPbuaYM2FabX&AbNnAv<5!$f94XE!&M8h57ZsNjmlanOR~6S3*A+Ju z8$2Ivj$d)8IHNdHoK>7toG30TE-5Z6t|+c5t|_i7ZYZ`tNbi6Dcs?xi5h~`trRE^{ zk>af4oZ>`rQE^FeS#d>iRdG#mU2#LPxv6zLf#OhcMscJ#t2n1PQCw79Qe0MCQCwAA zQ(RZvP;5S|#;-V3oKY&O{eo=8raanOiaaD0mab0mkvBCQq(m(#&cMig#;*8=*vAq8w^>Zpe zQCw79Qe0MCQCwAAQ(RZvP`ov?!)=cDCdE4y->dkr;-iX36hEu@tm1QuUsn8@;x`mu zQ2e&yi;B12Y;2J4>n6oJ72m7)u;QbNM-)G+_^je{ieFazn&LMUUr_wE;){y+Kl<<^ z+0Wd6;NXLwe&`ntJ>4jjj+786=xb);H)mINML(_TetcVg3%&K1xSKzgyi$XH)Kq@g-0T_|nK(WW4-Ssf z@31$239z|0{wd&B{Ye z?uPczUu)aJ?L|A#J1j@`C9#c1Sqh_o%!hXvS`w7;nFYob69Xt*dwC^zTBf_Ye;v&h{oE9-SevHCV zsgK*L=1ofD{p&f%9->4F*E(r_a#=qN5xiUd9O~Cq1=+u}aXsa$A~q}fv@4Ov^^cU- z^LHIpez);AN~nRxdHnn+UG^{I=f`XBw*Qv~UHz>ebt<2F|J>%g?*HqqM(t*&ynimI y_x~>`ZR6p0PLdR9YlbS;A8!9P({*1rQ-WHewru4&S4G~p;Cgq_Ci}-_wfVon|KDZ+ literal 21784 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 g@wTr&D=B69Nle%ThXiJ3$Fn=b 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 ScH8;w`wU5QH*G%O;r|9dU0Oc? diff --git a/internal/ebpf/bpf/execve_bpfel.go b/internal/ebpf/bpf/execve_bpfel.go index 1b73d6db5..d463e5a10 100644 --- a/internal/ebpf/bpf/execve_bpfel.go +++ b/internal/ebpf/bpf/execve_bpfel.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type ExecveApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type ExecveApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type ExecveApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type ExecveApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type ExecveScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -78,11 +106,21 @@ type ExecveProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type ExecveMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // ExecveVariableSpecs contains global variables before they are loaded into the kernel. @@ -111,15 +149,35 @@ func (o *ExecveObjects) Close() error { // // It can be passed to LoadExecveObjects or ebpf.CollectionSpec.LoadAndAssign. type ExecveMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *ExecveMaps) Close() error { return _ExecveClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/execve_bpfel.o b/internal/ebpf/bpf/execve_bpfel.o index 300111f3a935bc00457ad72806285b72ba6c1850..5e46cdabc1e47721b22c2b187d6ab94136ea36df 100644 GIT binary patch literal 25104 zcmeI3e{9@meaD|WC(bzui5ptiutLB6LAV6R@sG4MDGisjE^Z0bq)Bmsa=x4|ITQc5 zp3muBkBOTA&)Wcb6*JaW2~&_}X=t-1SiP;R78{eLG075@W&xW#iEY;CA0A`FnzVKA z&-1*W^Y=csLo1|BoBYVn_w#vup5MQ}-|v0>sqXU+Mp0H}d zycsb|w>DZTy(MPli%yvIumAKlF}(bOHJg1=V}APDYp*q{%s-1@F}+;x;$5nD5%!vo zTf@}`V*+T;P?jg+$jO-UL_pb0*+?0qG?W`Q!}7#Bna6?T5_g<7s>ITL{mNMFCr z%IbP;vS{PWzVY(DO+E~@eBI^y4D10oecf#o>H3>(#Ak4|_Ig*J@V=Hsn5;Xgp{zGA z?}F~jk$OlA{l0hj%>d!AI4S$1>|2tL)I{=m8ou-uw@%AVy*8rcBl*AKe7@@Pxuwpv zQ}U4(-l!fD?(30aJ>Lcy(<@ow+wu|HXf~}Ulf7)puMo~DYe$z%QMO=TTF1z`5DJr3uKTVEHb{E6^ zYU;A~@==)u7}tpF$8uAG?8+}U^*Bz&t-KU*8I&S{<#Lm=ry@?KoBFN26mj{Mn~G$X z*Hj@VtSmQ8l6%NgSQ;MO;0~O>Vy}MO;0~O@STIQe>6s-TqvP zxO$YE+`e6kxO!lm8Q;|d<4bn+!1$86k2m#_xxY8{k-6_T^^;va%1v3at4Fyh=h;pa zu$7oEWOp8yB0NW%`Wepiw8@>%n8%FY%W$5rO+DldTMpVoUMIWr8~s6UWB4jLPF^9q zdZE9`u3i`qva1)yi|p!EiY$;_y-JaJva44qGDmjxDn(|=u3n|c4B6GI6qzEsdX*xR zWLK|Jq(XM}Dn*K9SFcheM_#b96v>k3$^GOxavyn?+)JJz_mHQ^3GyVli(DbMk&9No z-up*?ZrS^A%xKvMKLfw@KDgP=_uc1AHy-5)HxA_q*Z<`S*YD+toEwLUEM-4sA7w8k z$9IC`I>GUr;5bgi884u0rfj5)Q5s6_FT2l~cAolqz5ASLr^oJd=CnJv%G2(=Do?v} zsyyw^r}DHrm&&`(nQlLs=6*BH{bri`%{2F$Y3?_>&zW|=!TV4vcb_xW^Xl$%rhTs7 zea@V;>!TFuaqFdNirh<{A@`AI$^GOxa+W+#&XE_$Me-uKLS7Heu?@b}axXxazDz*>I`w|&azY3273hELbrkq5 z=x{L^>qXI^-;T?7tZM9688N5J)wbbnQ0&}6UgE<2%AY=Lze+zR;H6)sFDvlUuQE>; z;lBqDcjyjWn3Zt!Zn-*F(`SAThs(Q*5vBe+jiWE`2QKcRcR+^Ai!%?1n(~58dsNyi zE?l-BXDR!g@CkT5hmOIv2)_mocSzQeFMFrFc4~*r%|-Zic(_9?xcI!FMo)^>xtew) zXxyp1R)kBOo$CIdF8!f4$Z&a`&Mw!Q^4#RGfl*n<2apI6?EZ2abeW&xWPXSqh=*O~ zd;(rvxUSM4;-sHD;1lpt*HiEnc$rhapYKLKaEI>2#i^E~?}liHLGqRTXs3ESh&ZPa zo`9G2BYH2qdsAs*vKO6q8OPoO{esi&FH((Qaj&QDU5HnK57#~A@;dYY>`sM(aZTVd z3WM~ayn)!M?!SVt0C6S0xYtvU_aa^eK3tCpnfbmylyA7t?~+pCZnQT^|1ZM-hkL1vPpRm$x9S9^;dM-U(gSgShuXmor4x!+Gj*R;Hli z&jj#8P%c3x;76f<7_tIikO(L$hD!pHzZH9yFmZPNJpl!MBz3S3^?Q>f|5aQbhx`pl z*ber&V7W#=ipyUkk1T>eME|BP@c|6|bQ6Dsuk9+~?Aj8ac= zcfl@t03WBGfZhQ;30Z+ZLwynY`=R$kO2(Ito z1ulSZ7X>bWzfTmn0RD_9Z~^=|QQ!jjM@4~)!=JaB(?3W(fRuAeTmXMT6u1EXmr?%+ z>pv<+IBBQMAGm$?Iyh1=$>iA!7tTJJeEgA*bSE!9+1s5=nnEd;F~g~1GBZ-h4`#+p z<~p=7Gv3*O_;MW|85_Jhk{Jjji}8C;i5b_bd1!RxY9JSLEmJbrQ$yn!Gmsz6CDWth zNHLbqrwZw8(gmdQSKACO?Q-dmOQ*Rql)5@*3i}4{WN#zU@T^>Rnsa!5UdOed*Ud@bb!tm$-a`ZvD!GWYyS)xF% z2?)VxzF?!}pqTOYd!;V8R@*<8m4MA$Ye?GRQl|>p%}Caqd3w_@lpA)@@|i1xMYJ7b zl1sXtsb+0cA^-OZCG$vCa zlQ-$n;o;Gdq@5ttU400sNM<-!;4ph5`cb+vj}f(VqS{TC(uJbQrbY(PDb<3KnPMh= zJ!1;Fldz>zLqlVtxLWu?%)Ly0BsFw0b2)eAWcs8_(+X%!n}&R*FrFU?n6rer)bV(F zbY!d$$b1QoA4BOU&Pdfh+V)gS5Xa(Gz?w|;&&j~G1HJtULGGDDh!S! zhcm-tnL-@qmY}UA7#n;xGkPU{T%t)DNL%H0l*Qgj4i5Ot#`0-oX5&eHf_x@5 zkQ^Vw^dBqaCGQhwWS+=^suodWJ=PNV2vX_@TZT1sIg_l-ZD6e6^1v0vvnoh|3Zn9; z4|azD>xy|?&0va*=ku6UNm+4)tAhh^Nyb6*Jvg2l!0NB`N~6Bpf<+}+px;1k`)js<1YkYOL@2S=`69>0Q-z?fdo#E-gJ zSslyc84O^XAB#IOHnGfCHw-de?PkpEw$yoZyLLTZ&B>;+^L4B=l1^U9$WD&+n@kN1 zU~OT4ZwcBZ_Ld2ai58m989SLXC(aZGhcjb^)Nn32GRE3m6C3vF0!(&dAR77{V~z+= zkUK1!lONViaDmd3FsnX9m`ugN0T#65Oq5vTg9DhD+r&gb(ob320EuMx4!aJ;PmBFmzw4K9As65>npnvhW*4DQL5ukww+r@ja`%MvEs+m zg+NeNzv#!0>Fgv_`Z^TLNHa`EmPJ~QNv!&zWG*G^)?CexVsjh9u7Y#H2Bh;iWJkuZ zK@>{{1Bx^9^5|$mhSDA!#vajar|)xvR}%rXl(qceV;8!U7rM_r6qj0{O*N5Fxwg}t zroq)H?ikT%W5MM|D6K?Xss$iVf3kB-E6#8s)ePQj}Ufi^xd^`J*$em1X7UNiLLy))1mV=C7m6OX`+pE@&kd-S2 zaXUlSPQs?W}^vx4ZpCQHxOu)EEMp*S%f$;4>1WUN;4U(RbqQRho{u5FeU+%`BbUJkKNGd@ z93))$Fj)Fo^7{g~e#pH?5%z8#ip2k>gwICJD*2y;zZSLc>m~dr!Vg8w2E!qo!vvIY zgBMBrd!zP$&V<{+^%tWi&hRtf=*OZ)zHF87r0_SQW*)lmXTUcvM9o5okAN4!Qs3W0 z_`z9YFtsdy3*7j;F)QTngZIxEv&!`U4nD9PHS6Tt@N|Fp71W>H4Q^OP#uz^-zfZz{ z7&S5Su!R38Y8uHE;Wf06{3Y;_SED8faRWF`_U-E;{{iAhF)4edchlnGoNM@I{q=iM)XH2ZB1YqIi}3BZSxAjfP`frTzZ~eiJ5jv*IAc2N0eh z---864J}yLinHWL5nkVh`jejnA3RlO<`mC|ct66ILoD%E$lsRqU0BzOH$uE0;W3Q6 z%$HXYKlXLJ8zML32ikf}_BJwSujwM+jqn5CFeVY=ec&GQX@nnHz`G@|^w(41n&={EKy_65{>fN%A)({~7dWi0i>KW4e>$n9Qp4M-ZYDSG{lF&3*`Soc=T&v%mZoPgE%{)bC_SSOMjMx{{ria{AJFXY;8WmXTi;2Dd!yg?sm$j^}%$S;v)kNux0$5v*COP#?Xpxp1^{FR^Q z`j!1w+Iv-!duZ2LJx;qk8);W3H-gH2(Z<_rpDDsYpQ61OHbR%*wdIC#PTBv%KBVro z_X^>lM#h(Cg0RD*FWg=u;}>>+#`t!SLIFoHjF>>;8A&U^Hy$|36}U-T!Z=UH5;McHRH)pa>2&>wiFh+=Tz& z?`6LPlt&O>>}|>}&zwg>^ErllC~<$v_&J9rp!_DJ4<#YK;!BWq4W&bwqjYuah zuvcUL68&%cjrKV0FVNnn>_0)c#ILA)zDK*%S6pDP?)QC(zo_hO3>UNXt=#j96TS;R z0WVJY9q^L^a6a7khwxD!!0>lMHgY}t_)FXmJpXT(KhG(EW6IY5r4UQ~mqIN4A^m9%AXMQz4e`G!h~10G|(W zC%7-fr@*-o9|yOT&S#ex(m*O79a(^Gr zFRQqycvA6<;yJ|&ikB3xC|*;%p*Y6-Q!&f>X;$p-UwwF&3hz;-cb7#WRZM6fY=VQoN#gP4R}}7;o);`9 zQhzIMzvT{pXS~@68^88jZ~4NVkxlE+(Dh;Yelw5H`fI)}+HA=7l?{dO(9G@Ag&JA? z6sX#|EuZ99KjCl1*NcVJWz#xV8n%*SY5d1U=g*z%OupMdv^&w6Z0~aDWM}d|!44Q}iQDD`LM(Y<-f4JUq&zN* z=WV2ztV>X8A^S?$m67;H>HT|0pN6+99?dgIEJt{vYH`ZyqfQ32AAyv1`t*&o%m09G zSN<$JCC2lC(W~h_zjuf7&HG)9enyn?<+qJ)+GEe#xRkHwVB_0hgyZ(^09T0{b}s?8 zOCK=(s!HI?_j&vc!c`O(B>&V1*C79l8ghF6eh-PaYyT?S?=zR~l(zWt{ro!s+jiw2 z>~e+vP<4PVU&eIX^3S{U6{eT+55w#7--^QP&c8N_pbC7|^>h8pd-t%@b^R+C)D~f* VuXVdr{(XX^y93^r-|T|Te*=!xZ36%R delta 5564 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 I|GAL(58~HAivR!s diff --git a/internal/ebpf/bpf/exit_bpfeb.go b/internal/ebpf/bpf/exit_bpfeb.go index 48d5ce17b..ce9bfc931 100644 --- a/internal/ebpf/bpf/exit_bpfeb.go +++ b/internal/ebpf/bpf/exit_bpfeb.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type ExitApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type ExitApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type ExitApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type ExitApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type ExitScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -75,11 +103,21 @@ type ExitProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type ExitMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // ExitVariableSpecs contains global variables before they are loaded into the kernel. @@ -108,15 +146,35 @@ func (o *ExitObjects) Close() error { // // It can be passed to LoadExitObjects or ebpf.CollectionSpec.LoadAndAssign. type ExitMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *ExitMaps) Close() error { return _ExitClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/exit_bpfeb.o b/internal/ebpf/bpf/exit_bpfeb.o index 4ddda18ccbcbb6e849367373f04984c26461a3ee..cc57f9c8146a68f6e8f0e5b2db0c6854112b078f 100644 GIT binary patch literal 10432 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 delta 2212 zcmZ{lU1(fI6vxl~N@A*QHl)cWt!7E{h3IzcM{R1GEU{^0%|k2!3xZ8(w?vG(Hj8XQ z+3kZ^pSpG)nun+nL<3fc)`vb6x(}&DkrF7BN=pe+G5FFv1dJf)|9|hy?pW}^%sIa^ zXJ*cwGdo*;d1Zeo>290*HZ>Wj)tb%q!J0_eE__$J;;ES}%>{u=o>;>2b%1~BKonrhfqcm_^nEDcciVHkTIzUR;&{sy`}v;^$G zq3KWKG?*Lx9fQ2V(Y$^oK!@Rf9ylXaaka92N}DUFKfOo?ku^i`4@5bk(VQe70IoF4)|T% zVP1{3h`qSDBbdO0Va8sUxMR334!$_#gW_HUdpZH{4RIHmz$HCS#>MpJqJ+KkA|o%dABs*6Pe@qip3mX)%=&p7ffKyVkWQ=v5(E? zw~G{T3&R?Q4mkaUX4ITt=%+QG5&0e)`oo$(#cAV&{87zci(J_XK5FqM@VI9Dgcngl ze^T?WB1<)>zn_g9!Q&!7w;&*IF*5dxnqNZsIDXb*j+Zo_6uHBM=OeCM+6FK$IU8)* z30{Y$#8H1b+~yF&`jEYgnwO$+Gl9qdpZL`W#&NtH_qh?ouR}-18$~%>^4*^F6!W z*dDdg)9<#_sYLINq0?{wGZJ3JqF%JB+IaAk+DKJ;^H)R%b8?wx$JX8`z!`;Rh?!=- GD*i9+Lf{zy diff --git a/internal/ebpf/bpf/exit_bpfel.go b/internal/ebpf/bpf/exit_bpfel.go index 146c15056..98c83f8cd 100644 --- a/internal/ebpf/bpf/exit_bpfel.go +++ b/internal/ebpf/bpf/exit_bpfel.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type ExitApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type ExitApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type ExitApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type ExitApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type ExitScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -75,11 +103,21 @@ type ExitProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type ExitMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // ExitVariableSpecs contains global variables before they are loaded into the kernel. @@ -108,15 +146,35 @@ func (o *ExitObjects) Close() error { // // It can be passed to LoadExitObjects or ebpf.CollectionSpec.LoadAndAssign. type ExitMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *ExitMaps) Close() error { return _ExitClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/exit_bpfel.o b/internal/ebpf/bpf/exit_bpfel.o index 92dbc6818a50023a13ca5807016b2179138058b8..6471cbdd2ee0adeeea878fc2a1254bf64ede9355 100644 GIT binary patch literal 10432 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 delta 2097 zcmZ9NUuau(6vxlKY0@Oi+9qaATemfXHjPDN=AXIFZB1ME5BE@|pii!4%cwd>T#II) zq7XtLkp`=sSkY^tb!G(J(xT9?U>y#LhsNv>+3i&~TZ6oWh>x+_+E6_4=@RnK}2Cpi|u{AeNbN(UNAro;V zlFEIE?hMvUc^onN4c1KgGsFPqyI=Vt;)Y8iuUfngJg9sFvHq&au<|{`z;)cepovaw z+{E`HMT^7WG36Io#{y1R90r$_kD~70!4xZ3H*Eu!lpC7w95p`)D_~j^*Pn?-tRao- zL!LpTaXIW0IQ{l`PPbj>^pYFU1TBb2?pDq|#JK~ScwYzfD_1+@^zj1Mv|d2u$Eyub zOXKX2_xMfJpECD1#!KIN1)nz&p47u-%@^z>G+!EiVz{?$`@sXBw}N(lQS)VOsak7= zh>6dabAD6eKpcuyE(a~?9r5``jEX)PG{0N4x8WS0^=NJU z5#wx5m|$!6iKBz}Rms=oVKbv1tt*28tXP4VJe6>Zjpmb7%K6Y-LFzT*bhK_MSBC$8 zWNWrvG*>zjk4p%z|ktEp0!{{Tv9=6V1C diff --git a/internal/ebpf/bpf/file_bpfeb.go b/internal/ebpf/bpf/file_bpfeb.go index aa41f2094..28c624010 100644 --- a/internal/ebpf/bpf/file_bpfeb.go +++ b/internal/ebpf/bpf/file_bpfeb.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type FileApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type FileApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type FileApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type FileApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type FileScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -90,11 +118,21 @@ type FileProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type FileMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // FileVariableSpecs contains global variables before they are loaded into the kernel. @@ -123,15 +161,35 @@ func (o *FileObjects) Close() error { // // It can be passed to LoadFileObjects or ebpf.CollectionSpec.LoadAndAssign. type FileMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *FileMaps) Close() error { return _FileClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/file_bpfeb.o b/internal/ebpf/bpf/file_bpfeb.o index 2ff0423638709ae6cd7498506a98696a022c3436..77478a41aefc426cfa05720e249cc9cd43b86524 100644 GIT binary patch literal 167576 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

~iwpW#p8pW;vAr|~BI6Z{GMWBhUaBm5*D#69?j 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 literal 77176 zcmeI53vgrCdEYO{ePE@PM6I-3t|dozWm$&g)e8HN1j(`jJ=P1w8wt@PhHNeqK&r^k`|cJCSE{xO8x8=5d&dV1ZY_e$8HH}Zs+N z;;%WpqN7HRU!Aq?I^Jj0UEJi)+pC}Qr>xs(&X(t4TMTb(-m=EKT=vo>-`}`@bxc!} zboFGEP2+1(UQv+k7p!>2eYQTu5nJDGJ~-c`TyO7uHm8l}&gaKN_CyTM3+r3V3xiU| z?cNE~GOz5i1-7FTg%{EGEy(_g29{0B|1+|8&v)A|W1s*2+D+qYhI_ql+4)95`RlfM zq&zL-URunXij@{~&O)7ML(nkPh#BA8<*>8^`ON#qW9;0uMmzQw^O8HCU)^cEP5dk5uyoF*`>eS8!ei&` zL@~DGY7_8T`84i3Yw36yx^#-af^zKKW8!H#S|S(j&6mgakEXL*(z#H1v_38$SDtRY(63)K#WL4tTg}6g zmCT2qF#(GTvXzFlccs5VwtY*(F|ci~(r_GX^C=A{ERRNvJ{~gDoy7MImxitTXvpf= zaK^Y7LpGn%Z~<)dDGiswaigW-3OE5?04Kp!a0D0JT7@n^E6_5u0L?>l&7P{dMf3wUebqYadIC z)-IM7tvxLD*RghfS;YLai1}v`^UosYpT)KrY5jGqo9BGf9{qJJt%v*TSabiezmCOq zz;M-^C&duXo8cvJ#%O7{2FCTo@G>|L|2nt;UICZE4R8g#3SIy=!By}YcnRDB*TC!G zWpEo@2iy6uzmB!*#ZrGAYwTx#9cxaHE!VNH;{L9C9$NYoo=>@T=BL)obBf}aZxV9P zPxcPt`OAwoeZ3F6hWoH1;-u^5yzIrAT`v^>DbhKuzT*DWkkPllPTuM{@2Y*i@?6tC zf5Cn0vFGf4)ZqPq3q4QnKL0VpNuJw$)Ren)4%eyY?ERY3Ih=Rr?EM+JFK#aMOXuwU zn9{knNuYFY9omAfL7UK3Xal+etwWcgHRuww3SEF!pk-(Qnuq3~8E6WcgeIVIXbc*K zMxZ`)1Udu_Lp`XSuciKIKRdsd&aHu)&{b#yx&p03m!Yr==a#@#=mN9?Ekg^?JTwQ* zKvU2pGy#o6W6&rx0`;LI&>^dfaGwtwF20EIi1V%ZB|9$n4%!Ej?!FU0@743@g3ozR z+j2aN=LuuyENi^}b6(H0qtbMN`RG6AZQ1j2aShspu0k8o6=)s046Q+zpjGGsv;r+d z3(!0?2hBiJ&?GbgjYDJ5C^Q1~p(D^CXc+22+os?9>toDs^S)`1{`$DTKGuN{e16`4 z&a2O%VgLK5sDpY!7Sz5kpS;{o=3cm)i*K3oUGz7H>hGe+fp5;z530w=*$a00vl zj)N=U7`P0Mf(u52>$;sjKCf9PXD>BnNLcK?tYlP59Zzv(fd<+K3?ekV{^Xt-#<3@ulw&G zo8e@hE9m>({r8V?Kd1lP*37&8_mA7w{`B8J#(2o1J?h{bcp01l*T5<85;zI2f)n5c za2#9#$G~N96kIU+17DZA_b+?Acl`FQbM1S^-F0ftOuRq%@6GnttJ<)o{`86z?Tq+`H?@{(99kSN}cZ#gu*DVlfF#K>P0*>j;tetgSujuUGB-vS{Cv zkoU~Nn0NZ?Rns1Ne^6&&_rC0fzF(>m$!o@%t`s_IFy`?@c_e zFT}{U-LubUOXu;P?|I*j-}89S_dMS7J&*T%&trU_Z<_>4=hvYv=o+*MU4=HFE6_T0 z8CrubL95UOsJ;JCI&begl+G96o`>e38E6WcgeIVIXbc*KMxZ`)1Udu_Lp^BQw4c-; z+Jde@n^4S;=NsS^XdSu?twEQdRp>#zYq2H<^ywj z_PNjtt#3=`?YJ(TA2Q)O zzYpcs!}d0c8fFZ_W2;?fRiOjCJuI zyB;XrY_Hcl>*K)hC%?V*@i}w;b=Svp_I!NK{ti{?X}eB-MKh6Y?CCf8yHGoAyzcYj zoN*|f#`EIScwT%O&x=pvdGTpnSDwc6;?uY}n5;5;-3%|KJoBs2kyLu1e=Gy?UZBhVpe80taWXt#A}3%UkvLNTA7 zZh%*yb?7p*23>+yp$pIovpuTu&-!)bDYh>T94&88; zBnXz|${XTnSap;u_HDYF(pO=Tm-i!btm(yNzgc$KF4rZx^OwT``zEe>ZA{m$0F3*9 z{x3Xi8}bgOqwmKawt>R>KM-%jv6kt5_Sn_klH{%bwa=~`y|6YHIybD=@(~-#{0F?a zJ=S~3+k83JI^vafQ^!k%Mu=e$e9?9`_^6|Uo&@=yqT85tmVc{$boqVVhQ0jVqQU$kNJC^pety?|KlV!am~ct_HUHb?cuXcF>4$9zIi8kdEvIg?IQHeZ zfaACv|9v^WQ?xAmXK=hC$G<4YcZq7kzbwah%VAuOe@%|{JS)rbZ_DvLa=aqP*al+m zNV3K}r7oBJXuy43j{l{^mCc<`E(O!x?-viLlIiDPkq(k$GZ()k$8mAjZCQ@*6ZK_( z8SZg8{!O@N8P?-kYU-^j6SVVxKLkiy(=ygcuZ17Xxj(%I1Ge<%~Z zxb1!b;e-C#CzEpWss9Ih`0JSYCHN-)-anSPy@Ve}hcSn*PZi{u=)e;r~z% ze~q7z%4_^&4}XpSb@)Hh!(Zd?5u>E>AM4?-@mJ&|Q~#gr;ji)UlnGG%Q$74O{yO|W z+{0hvzefh4#(%PhzsCO-{C^7mA{)k*G>>*> zm*eYY*UgvxMm>;*iPKZrabJ@-d;2kU zmd}p!U# zL^?GoY0S-xj%CxPF6o)kXVbIAS*>Aq#v7YHb7p!fZR(9yHaa;us|U77)=OG9 zJ2N#pd29Am{;6BXZq*hzB!`E_yj?TdxwA7k{fgqU~b&k?azXe0I*JA)k^xiXt)IZz`z`diyb7&P}x9>8uRy zvokYtI;8UxOFxy>2~sAE^yv7woVzk@9`p}u=uN{nyJ7HV&Ct!>a?jkvne6P` z=$U+aY8It=M%~id*;BKodnK5(l=PegkON6wTreA@C&tCK3)WLxOq^B3K}V4ZrUPWl zL8PJ1PK?W#LOFsV#Ut%Tn<=#hGCen;r;s|?h!Xprd;FtEtfP!l2?t;6Bq_P5HaF{R zV zysVDvF_}8#R2ZF1=STIl^G?r9%e*-$lY$r|<1scPMr&$T&hJ9elb)QJOP`vap3^=w z7RxgxFM8JlwX98W)T{N4v5S`w+(hCoul=v_y>UA6>UL}T|@BX>n@;ly`SmYU{4KPz5`BmvtFF1#eLRe142`0v94Z9Km<8`Do> zI@C@G8w0EphO{6IigP{OaXk_Ui=i)Jj|NFu9E7i{_l@nkAbSTPe*9Zst_!nTTAp85<#W)g#zii7IGfIU6%B*ABgHjE)Qq z<>qK>4k9}LiC537tI@d&TwjT&vn;(Xqaw3n%Db0FdZDz{MHF8)1uvP1wraL%mt zDqFxW7)7rGjgcIkJ95Da9ns4*cTu?UYEq(hCaQ>o$s9A2b_b<5>iSNQ70DTyrC$MJ@WWN_owfDJhgdF z-Kw*+i>a?JIN)syzL^1UQ|~pr%z*EBUudYj$pKHnk6gew9mS{#j_z)o^eXiR-(a*2 z)#)*HlK&5{zFiA-te5$9J<_8J!MY#uPCj`5@rNEg?j4ea+^jb_F_xX0)#nNNe9+fB zX|ipT8*RFORc^R9wC#>nsi~kNutPKBuru_1t zw*VF~TU95q!;NDg`<@Sjw7sZ0d^Us3zZ zgqF+XD^E>E0=z?5`%&Y&EiMNd{)Ft>uPLzW*Ias$F3 zga;lQFwgyze?$4D0dE=Y_;ul{mj_Hcs=x9cVHsK`zCQfl{lGS_0lr#zD89{Wf)5K{ za`!fG4Sb*QrHuh^9h?)s;x#Eh_~(RoH6>i@L?FAV-o^?!Z9lO{9%uPLud z{lNcKc+WQnJU_s@gd<>AzZm%cO85ae2@>F2Q=v;y-+~oOi_40ADTs zD-^#04u_@wBZFR(cny3^{C8X{jUnx<^*=6rnJ?!Vu^-?|#Xk<7k?^~281yp4Iq>H- zeK|=Nz~2zweQ?mL5ibY$67gRRu!e7f_s9d%-O)jBowyy~OT<4c?X2~=Tf&D=Zu27G zobZn1HZKaE5x%lK=*0qjiEtcTQU6cKyb|C`gp=SesJ~1KsQ_OhoB_YA{+}N7blhoq zlrIs^gMVLnLHa+yJA}*N|0MobJumZ4fOiWofd4}LhpU5LHNaO0FM+QTTRHH8u(Z48 zpHg0u_7_$DjB-lOC-BS4Ps;ft>gKC~inY1!y#aOKCN}oNOWk=)`J}MUW6u8`VV%bu zUoZTFn8!3dXP*`%eXWPHPm+aU5wq3gQ~jNNYJi=6YJ#18YD-v6Uxv7`PhnAIXP@L$ zGMo@q`=sGCeP^E{@Sjxoq|_Jw&OW8U-xgK-loQqTHN4uVJp4`J<)c9UGBizo#!kQ< zY5vM;pQ;pIy4r+y_Nf7X?XQ6)d+oHzKGnPZYV4D+_N&Whx7W8%b+l{WKK1QW-#-12 z?UT$;y5_qclcvt6e=Mwv51qG^-?3Y+(^h4@0KQFlhfMx4;siJ${)4Z3UIzRb;g76& zo%NA&QaB&*zel(b;Om8}0apJdVVy@$$gbDzb+Ef`clJqHuiK@_ru@#{ts}g%ce*gv z^xUT3o>X@B&Rusqd#CT)slT&#YLB#i)Q;(TECY7-&e^AgxU0P@i)wsl?_Ae8SL!cN+7)2JGDm|-fgSo--N%jcWVJwd$&&E+wgbx&X?<4t)KSSz?!`mAk{RR zx|{V_o9vzNkc7~3nSA^9uD>3`da1u2v+KA1dd$ubx<0$;>oJ+1^d9E^z&!SZa9qBE z?~9wxYi?6}r}Nke+11{}!Oq^u6m0yRy-5k1c~R2aadpVpJB{z`O#$IW%vP39^>_AW z3GD36GT7N0xpiXFH}*t~(}w$j2Set5pr+^Si(8Kw`yxLf5XSuO>`Mgf>`N?Y4AqUkyN`%4ZZ^r%z_wA2u_rCq<+n@gPCYfgf&zF9f&zp?>k@-pA zvG6fz>U?@a_|$j1^O$m6Sl2h|?>4nRI-j19UDrDauv_ow`bPcTdM6{S@qbIw+wpR! z^PJqRcghGaVz!EWYJ6vJYG7w?oc(e3#;te$RMOx5T6ewkf0Y|{y`%Z7UAb&EAnTtqIz*zYxCfYI!~{ z31~RwqrxJlo+jV^{ks1By8e2~oDco=)DQRl37ww?WPZ|j0aOK;_AUy4XMd7lXYZW7((r2Ua`3mM zx9?N9^whr$f0tiHSpA*7)BAZ^9+zK@(pyG&XYU&DclK^Iz-sT-D1Hmrul3C z4@m#&yP})y-2>fmV(gu;juS0s-`@4#7wq3Z?7uJg*Jb@??48U{`i}d%FbV7Yc1pPP zWOp7@J|pbxo$^lzJA0>mk8niNaPhAfPJoeg=Y94QG8d}-%ZZ21i*CJF2(Z3SQ5M$p zoc&vZzq5bKU=g#`-A>c_IvVO4&9c(+rpMx;CsOl`7T3Dyr#f;Vf_uZ*THr0Zh7}aH~s$G z#mGm$M|Uyu(RU~=Mn3wi>|*4j_b@L;KDu_i82PA;z8Lw~(Y^KOpeGj>wEb@_n7C)i zebJnI_WOB3ud{OQY4}FaQI7SxN!@dl#c#tsMea7VoS3xzcT=A2=DIZKRWL!foA-r- z?*GS>XS-JmI?C~n!d<_Y6WsovDaUs6eY&7~5$-yd1h=ed2XQpz>iYZ!(qE$V--mMQ z_l3GbkjHwoAO+0zP}g@uh;SVE3`3Ly9BqB z2(S0Kg4;aYSIAw%44Pk142Jf+UpM8vY*W8{*wpv3P5tukP5Cd|)GzOZJNL_fH08K# zQ~4i&JNL``O!;AW0!4iu>2tsAM>%`~FuQ2P?px56u`CehZw-t2%kjeK7 z^IOM3_xGFfUtyl>1>L^@_n6V3kG8+uT%>Kul;_G#?fkIoXPhp^ZnzX zmwZK3wyQRsFSnZVOFBloG0ww1N$whA(9>Vr-njj|DbL^6mGyU(T5F%bVWRFJD1A+%NZ|JiYtH zz0ub#(Kk%G*KDfqf=TBZ^S$?OXt`%+^1Wu0z5bXf|25`)fnfNT;hv%P-*4)5&8F)C zjXUVMZyI+~`Xf`$cWx@Du8lkiulMeCMX~<#xF9`SQO^`QEwdd^rVo?w2P` z`K6rHFTaNLxnGW;oW1+yx?s`G@mEc{*KMlTCrvunnco)(M$+Fa*I!s~1s&!1QB(fw za6Q}g{AIWojCS3JOueo%&#k(y_Gr*Mz)s%3Fy%b3sb5A-IS*_q|Ldll2R8M~yW!6L zvS!M6U{k+*5boSB_nY!dIjLV>K>FM-2T)G#7kO1jek;A(I1LD|z|zVgu` zpO*0Io&-Dhk0E@N+&^d1H<=rsbzFDua;fY*ZZEj`R3E}^f$Wq1g^uI zD5s97J%Q_Cm%iRF+++T`fK4E3+C}cc8h5$=!RErpr2KpA&uSYVH;;yld-uA+h5vmC zwMXox+g4DX&l>lx9dzM;&!iKu7bwqXjl27Xi~LRu+UGvgZrypzNBEt_y*qEX@Q=zk z*kk_lfGtrB;fIa;0awgU`o5I+%FdGuxrdJsdOt=t$;O+Py{aIa@+W0qKs}W!vd3lD z&4pJt-JJijMZ=$R9`OGMqC*(Jo$#o?9AGU^{vwy>jmA&qBA3U_N3Oqu<5Szm&3EdresS4#>lI%8|EkAx>ms*L z($uzF-+F+xee^k&ZWpV4Dq)+SW~=kX^8wcRLVw>yH}%*4(Eqogo3fU-9$=lnRs;Nb z;e)d4rs1_tcPq%Iyi<1fOio#6{U>GDO<8B}Nd?)I56J#;1=*A%vVU4ZHsvF-zn~zS zvYs0+DafXLpX|S_Ae(YR_SY0-Q+`DD*A-+_enR$dE6AoiCi{04WK(`x_T5@3*_7vG zzc#=nVfiYc+0C6&&k(Us93_qu zCy6t}dEzqh0`U^@GVu!WD)AbzzIW#8tK&6{`9kZjJVG2Hju9t_Q^Yyq0&#`7N?aqZ z6E}#P#4X}Baab!ZTc`fS`rJL}@2-nn_yqauGpu0v9C3lTLR=-T5!ZUQdnXXB22;wW*PI7yr#&J&l3s{z*QqZ)CYxIx?`ZV|VM!&o0`eKo%k;s|k!I6hFA*;juMn>iuMw{kyIYc4KP}%79=SU9iKE1E;v{i~I8R(AULal~UM5~4UL{^5 zUMF@pf?a)whP3x=e`|aA#8KinagsPgoF}dXI3oE~iEG4l;s$Y(xJBG14(mmYY+8TK ze}p(f93xH;r-*aJ1>y>EmAFP+CvFfoiCe^N;;_8yrCX=|#1Y~cae_ESoFgs}SBR^` zHR3vPgSbiDB5o6#f07-nKOQ-__J|P2h!eyq;v8{-xI$bdt`XOX8^lfG7IB-{{A2K7 z{q+G+fFr~);skMuI7eI{t`Jv=Ys7Wp262Cjd-2d{UckguapLEp<@hb5e@j9{l=RaCsO>gMhZvQL$#8KinagsPgoF^_5FAy&gFB7j2 zuM)2juM@jhz&iEEs~wJg;wW*PI7yrfa6;O%KwKfN64!|9#0}ymaf`T39R87Re{1ai6g`@ z;skMuI7eI{t`Jv=Ys7Wp262#AV_I;w9o`;uYdm z;x*!RV)x3O_P5q&=w03VEBnMz;y7`VI76H#E)y>hFA*;juMn>iuMw{k%d4Gc>(rmv zCyoX935l5?P7&vb3&a)TDshdtPTU}F61Rxk#Nl^$>#y}0A&wBoh!eyq;v8{-xI$bd zt`XOX8^lfG7IB+6d?VGLI6@pFP7tSvbHoMW3UQUVMqDRu5I2ci#BJj6d#L`z5#kte zf;dH-BQ6kEh^xdk;yQ7IxJle1ZWD*~Cbn$bWH;lVI6@pFP7tSvbHoMW3UQUVMqDRu z5I2ci#NJJ&x~9HkayUfn6Gw^T#7W`|ah|wLygy>EmAFP+CvFfo ziCe^N;_$(4{k480#1Y~cae_ESoFgs}SBR^`HR3vPgSbiDB5o6hZ=w1VM~Gv@3E~uS zj<`TvA+8eFi0i}+;wEv6xJ?{BMD-_*5XXoU#3|w&ae=r(TqUj%*NGd%P2v`Dn>c(c z)t@**93xH;r-*aJ1>y>EmAFP+CvFfoiPr->r&W!1>#ICO>=Q?cgOuRt6 zM7&JALcB`6M!Zh!9j5vd`@~V=IB}9VL!2ir6E6@i5ib+35U&!i5w8=Qhj!8gdVOd5 zUmxPh<~S1IlDNl+6T~Uv9C3lTLR=-T5!Zgc#`28eW!fL z=I&QqOMH;{ZsL=~;{n$7&>Zn6h@U6^GV#mAuLW4`&+EkBCjKt*?z^s*G7ec=jS_-`w`eNuyp)ZG?5B);u=R-dil5YYYn#&gE zyhAhD$wT)&_JKnR<1^Fw^w{*-sW~qX{4W*a;DgYLe{uXyrDQc4LrWWX*R*s(B`R zp?o_bf>BMP9iOf9?F7l5%TCSBdWX)8=4ZXxv6<1iv0OTr9nJS_dDBgsYU283LzGUV z_Kwr_4i>-L;=N-9{DaW~P1!qMFaRp)9h#gxcP2eLK0Y%$aoU@l7|Tx0W;ax!+Yh}{ z4ft;=jcwrG@l0tDK)U(VWOm#;G&?slH+o96c*ZEs2k+#A_aA@g(c|99`|i6leWyyy z${kj2w{n}6!%mM`J_={(5uj7xVXILfG?tEOcDGwOe9Y<*AT$bu-kH8bQMft<9=3XC`ta>G39Gk(B@ydz)H!qxoWo%p#L~Cff*X;78$Dv>Ff5#&!pin|0_MI0wnr_}rO3W(#iQHcL`$gU75Kg{xEGVXIOIBwmS z=o~l)DTML4Gkw$+!pLowB)-9;K&QaN&|~StCYUr44x)Mx9NRkN?G${Z_t*{w2uAFj z@1t{D#M}@f7`1zvZ5elCkYMD%xwd6&3S-W+Bif3ww2?ck+-~JIE7GRM^B53%6bL;6 zbP7CdH421E`66Fb!F zu;BJ*68S>$-S^8~oUl89enTSflH)kJH(s|6uATI@zSh&lA42$lzD53F6x97b4}y2% zJO1@8@^2&m3<7HY+hyncXT+^n{o9w@i0=FJmb&pBPsu^A`ltT04H2xrb|vSpmxsOb zU)^Klzft{lIn^uw3i8j`WIV0EhU5J8`{2FuU%`83?suP%OeenM?@0V!`L}x1|I!}$ ze`SmO*ALhn-l+b+wMG6Te`4cjteE;=CdXX=#|C=We+|ze-0v?SnNEDiNr~U9{srV8 z?Efoz^uJDNuK(Qln-Rm=tNxLkjTn1_`cFyx zUiGi9+4#ZwU)Ll5V_W2(nY8iWsQ%F{@^2ykj7`SW|9~8G{XdEEN2j@$eAY(PIWxFv zTLrgyaZopopF#YEU|>0R`8(%pBqFD&e(Q+;BY5B2g{SWD_DTF+?VtEBHbw>!)&9L( zc9*~Ff3-=y@*jHMMm&i7H@NQi#Q6V=U4r8P diff --git a/internal/ebpf/bpf/mem_bpfeb.go b/internal/ebpf/bpf/mem_bpfeb.go index e5a1a1c02..5f8e03f39 100644 --- a/internal/ebpf/bpf/mem_bpfeb.go +++ b/internal/ebpf/bpf/mem_bpfeb.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type MemApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type MemApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type MemApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type MemApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type MemScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -80,11 +108,21 @@ type MemProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type MemMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // MemVariableSpecs contains global variables before they are loaded into the kernel. @@ -113,15 +151,35 @@ func (o *MemObjects) Close() error { // // It can be passed to LoadMemObjects or ebpf.CollectionSpec.LoadAndAssign. type MemMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *MemMaps) Close() error { return _MemClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/mem_bpfeb.o b/internal/ebpf/bpf/mem_bpfeb.o index 789506c53f60bba3ebb51fc06a387b66e2214959..2618d083eb972a4b950235558494a4458267d970 100644 GIT binary patch literal 68248 zcmeI54SXC|dG%*kaw5l$qr@K(V4RKZgmrKn`6G!SA>Du-HpK}damXe(XcbBJn#lHA zlEWICB8q`+F;vjB21g(ZsiZ3nM_Ml(k3ZeM7%+4g8T_?2XtCIC7qOVED#?Tk4Z2B`_QKbVnDOQ)oh(h2Ff zbWA!b9gz-8E7Bq9pmac5mi9|a(xS8=%}aCAR%uq6k+w*irD!hGPcy+oMrWZrVm`hLmbp=ajjlUIc0?$3m(<0g53 zh`}#O54EdbZw~vTeAdpmWr-c1Q^xN2oO%YwXVS_=$LB4L!I`J2XMB!&>U@6>f8@!r zXHh;8joBCa)2jqW9%2_&Wx>cHyUM+2rZjm-i*GtpVwbGPyrL;-9Oxh@2 zENzh1OHG0UD-xHP_9hbaH+X~i3{&u>VqCJw><{v@9>ia$c%90 z`Nzad75~2YJn{F$=Ze28rY}%_N_>vu-w`hn|DE`3@wdhF6Usj-UZnWniq8`Njd-E> zuf_Bs%1?^vJMdqL={xXWis?J>Ux?{D@FQaS4*V@KeFy%gm_`GCLu>-S2NNNOz5{<< zOy7b3Tuk4Azb1ad6#TH5z5{<%Oy7b3OibT_zapmZz~f^24*X>?eFy%Mn7#vlQB2=~ z9}?4d;6D}9ci=w}(|6!M7Sng&F)@7y{(_jk1Aksj-+@0TrtiQHis?J>ABpKZ@Mp#J z9rzE$^c{FqOy7Y|is?J>XTrP|DJf#6g(oP@4)wq z={xZ6is?J>r^NIf_&zax2mT!~eFy$+F?|RAEiruu9v0Jg;NKL}ci>No={xWz#Pl8b zUNL2L@4z1r(|6!s6VrF#Ulr4L;NxQY4*V-(`VRblF?|PqpLo<1JSe8`!0#2) zci>+Z(|6!s64Q6!d&Kk|_!q_W9r!(B`VRbVF?|Of5Yuzg0}%fscymJMde?^d0zT#q=Hc z&0_iv+%Kl@z;6=Mci^89(|6!Eis?J>5ixxSJ}jp1z;6)Kci=(zeFyFl(|6zlV)_nT6w`O${bKqKyiZKuf%l5(J8-v{z60MS zrtiS76VrF#J!1L}ToBWD;N4>S4!lcD-+{Zt^c}cUOy7Y!#Pl8bPBDE4ZWq&c;Jlc= z1GkCkJMe48^d0yPF?|Q#DW>nhuMyLC;M>LY9r!kJzbQB;rtiSFis?J>tHtyk_!cpJ z2i_s3@4z>U={xXEV)_pJDlvTrZWYsa;8%+2JMfKS`VM@9n7#vV7t?p(SBU95@K1~B zJMi^l`VO2G(|6#Pi|IS?bz=GsyiH8sfwzk3JMhcI^d0!6V)_nzt(d+8XT*@H#Pl z2TqIWJMas{^d0zOF?|QVNKD^>*NW*o@ES3F2VO0v@4y#|={s;rOy7Yo5YubHo`_aFdw61D`LZ@4zd>^c{G)n7#uq6VrF#rDFOH ze4d!T1D`9V@4$^>`VM@Kn7#uq5z}|zv&Hlsc(Iti11}QOci^+c^c{Gin7#uy7%vFI z^ThoFMz|mJu_vcYpXvQF3<}4)W1;RVElgPPpktx#D=iG~tAZa_`n2>hDceK*QSqeo z5$S~VVd=Q^A?cX(LFuUU0qKbJKIyRZUTH;oLOLWpE*+HKBjre;zsJO7=}~FF^oX=1 z?UNRz-O_@zQ<|6Vl;)&6q^;8J(yVl=G$XxQ+9KT|ZI-T=rlo78Dd|dSlXRK1QMy># zAg!00%s$6B{Lv?;jiFPfc&_oN^a)evvnS@bpPGQrl9s={Xg`DC)=(2CdDI5MZuTlz z@bXZf^>dl!K_Wa~gyn_u{iW`DaRKa?hoDH0*8Ln{U-1u%0D4}SUN6!NIE8cP&z7oKsqA5PdY5U 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 literal 32248 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 diff --git a/internal/ebpf/bpf/mem_bpfel.go b/internal/ebpf/bpf/mem_bpfel.go index 7a8d011c2..e807e14ec 100644 --- a/internal/ebpf/bpf/mem_bpfel.go +++ b/internal/ebpf/bpf/mem_bpfel.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type MemApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type MemApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type MemApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type MemApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type MemScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -80,11 +108,21 @@ type MemProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type MemMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // MemVariableSpecs contains global variables before they are loaded into the kernel. @@ -113,15 +151,35 @@ func (o *MemObjects) Close() error { // // It can be passed to LoadMemObjects or ebpf.CollectionSpec.LoadAndAssign. type MemMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *MemMaps) Close() error { return _MemClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/mem_bpfel.o b/internal/ebpf/bpf/mem_bpfel.o index 5d167155c1fe6007eabdf0ef3e4c0424d1d8988b..db032814f4af231089eedf0b9c55148ca480c9c5 100644 GIT binary patch literal 67960 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 literal 31960 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 diff --git a/internal/ebpf/bpf/net_bpfeb.go b/internal/ebpf/bpf/net_bpfeb.go index 6f3c05914..c83567465 100644 --- a/internal/ebpf/bpf/net_bpfeb.go +++ b/internal/ebpf/bpf/net_bpfeb.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type NetApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type NetApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type NetApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type NetApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type NetScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -80,11 +108,21 @@ type NetProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type NetMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // NetVariableSpecs contains global variables before they are loaded into the kernel. @@ -113,15 +151,35 @@ func (o *NetObjects) Close() error { // // It can be passed to LoadNetObjects or ebpf.CollectionSpec.LoadAndAssign. type NetMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *NetMaps) Close() error { return _NetClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/net_bpfeb.o b/internal/ebpf/bpf/net_bpfeb.o index e33bd9ac6a36c08fa0c205773053d4ba130edc76..f4ccf10ccf7f3dea24b37193e0ec57d438ac052c 100644 GIT binary patch literal 70208 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 O6)I(3?YOc2)c*s4BcL7t literal 33632 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 diff --git a/internal/ebpf/bpf/net_bpfel.go b/internal/ebpf/bpf/net_bpfel.go index 95f7f27d6..8e87c33a6 100644 --- a/internal/ebpf/bpf/net_bpfel.go +++ b/internal/ebpf/bpf/net_bpfel.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type NetApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type NetApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type NetApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type NetApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type NetScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -80,11 +108,21 @@ type NetProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type NetMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // NetVariableSpecs contains global variables before they are loaded into the kernel. @@ -113,15 +151,35 @@ func (o *NetObjects) Close() error { // // It can be passed to LoadNetObjects or ebpf.CollectionSpec.LoadAndAssign. type NetMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *NetMaps) Close() error { return _NetClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/net_bpfel.o b/internal/ebpf/bpf/net_bpfel.o index 6757c2ddaced3058f26040363a0d9c24fd1d631d..217e34e79e8dc89e5fbcda368982b6c582c0c5c3 100644 GIT binary patch literal 69920 zcmeI54}4@-S@&=LY<70L-JUL+G?XpeZI?1zw%hEV!T{ScrCUgKX+zniQz*^c&SpE? zW_Kq!*)VB}1TA$e1x73~FIGrPl@Y5(tajAuMlCq{7L8gUV!`;@SEE#oSYPsDk@tDd z^E;WFXE)ofsPF6hne)k=-~FEd_uS{6d(OQlGw-`*-&WuFrdiT~=>AXxnFcfZ@+NbUkYK%eY&0Hv)8Zg>7e zh}YSYcl=nwNsznu%gkr=d0I6toJRgjS$sXbCz2EkX;>JTwcMJ*&@?m!?SUqtA+#H6pb2OI zT|~PrKnuLbX zZm5AKpiY9ZA^3NJheHX!SmKRYNzeArm(iu0+gvy^8&IxG%6p7~{5sp(U3h1!#5)l= z3|3PZpCP_33be7Vr)_-gi?jO^If_i~G0EPg=OQ0-zCrLY=vWu(eV!awqnsIc-8Qb{ z`ID~W`4@E^yUQl<*YSZC?iH5z2Qw?=!!4rgJAQlpqks^JI;tk!pgQEwxQ7E^_^&6O|eCJELM)*K$yE~6Vx9)NwLx*=tItq8`wo1I{ zHaX9^^Uti^I)jh6`uTEmrrqVAGjjdq%=4~*oLPiE2VHp?jfe=pJYax*OU9-3CoUw?ISaCTKTwBh*0GK@-q+sFPqQy3E;w zHQYmx-A3ENa$_5cE(Nbb_%^WE(NOeia2vue0k?v;f@Kge6v_R;!v2P$S0UV8PE`KI z;D2=$9Ex5E{tkEx_<8U};C}&M2>v#BGx&dl<-TNL??cfm5YAUEAOFk2{|kHp_@BX> zz|VnS2L31T`QUGYUkd(5u-p%=Spc7h@P7bzf&U)d3I03qM)0%Xmw>+k-T?kv@VVf> z0n2^ZntAX!2>)yFdhlO?&j$Zb@H+4_U>Ues^OxYY2>&18HQ>Jh%l+S)Ik4EBHGd8k zyR+u&V6i)Ez6KV%v*u~A*qt?h1{S-s=Br?_J8S+FEd8D}vtY41YrX;&yR+uYV6i)E zz62J#v*szV*qt?h0v5Zo=8wT*ch>w7c+sgfGhnehYyJ={c4y5WfW_{t`65{C&YCB| zVt3a3cd*!!~-C6USV6i)EegiCaXU*eau{&#i9V~Wd&98yQ?yUJ$ z@SIa?YGAQDYaRoO-C6T1V6i)Eeikch>wOSnST4DX`d` zHNOBByR+u!!D4sT{2W;9&YDNSVt3a3ELiN$n$Lp8?yUJ4u-Kh7Rj}BdHJ<^C-C6U~ zV6i)EehMshXU)T4u{&!%4Hmnz<{_}yoiz`F#qO+`1dH8S^C_^{oi(2Xi``lClVGts zYaRfL-C6S!V6i)EJ^>cHv*y2nr=40;0gK&P^Kr1)oi#rW7Q3_NV_>m6Ywib&-C6Tv zV6i)EJ_;7Qv*t&^Vt3Y*!D4sTd;~0ZXU&JfVt3Yj2rPDI&3$08J8M1&7Q3_NUa;7m zH9rCtyR)VQ7Q3_NhrwcZ*4zUYyR+s4V6i)E?goq9S@T0+u{&#i5G;0Q&HKS(ch*dR z#qO+mA6V?pnjZj*-C6Tqu-Kh7cY($3tQiN3-C1)dSnST4G4P~QYl>j8J8Rwp7Q3@% z6fAaU&2g~Uoi!t1u{&!lSnST4VX)YpHA7&rJ8KGHu{&#yfyM5uISLlLv*rj`?9Q4& zu-Kh7cYww2thpU5c4y6Du-Kh7d9c`>HMfDq?yNZk7Q3@%04#QA%|Wo(oi#bI*qt@E zg2nEviNIoa)?~qAch>ZS#qO-R1uS-F&AY*3ch=kt7Q3_NU0|_0Yu*VKyR+sd@Pt!q zGGMVgYic4y67!D4sT>;sG4S@Zp1u{&$N4=i?P&9z{$J8OEuVt3ZO1uS-F&6~kuch+13 z7Q3@%FIeo(nybNLch4{tT_iPc4y6cu-Kh7XM@G=tXT&ZyR+sju-Kh7 zYr$f7)~o@G-C2`xyeg3M=buOAK5?ecm!!ROWjt3Z??QgGmdljKJPUCKIi!rp5L}m`c8Rm5=6-NMpE`a z@qW&op0^ULB7F-fSK&Q_wMZYTbJL`ad+Xo-{ZUkdAcS0{CVP5+5Z5Et7q^f=Mg{t)1U9B zU3@N&UGus11lr*)DEb%7M{<}~ZvPRwDv zmosUk+XF@ag7Hue>h zUGroI&P5UWA;gQ&G5GjVgnkS8MiKfiG~E?HEPN+cS#xB7WLw6p7|A{*9u22=7I>s6Ss(v>)Mp z2p9F|H;QgXcn0C3IoLxK9YlB*;i5UrzoKXm;dz9MdV7na5rh{IF6!+wita*q5#gda z*mD%!jqnMCi{>!@kD~h!UP8EN4$mi|=zfHk5iXj;^OGog0O1vci{|irCyE|M_$0zb zb9nv~MUNo7ig3{!o{vS*qX?fuxM&W~@1p2&gx3%*n#1$OD0%|n(+C&M;rVA2J&Eu- z!bNj%qUzHT30FHofIu{Md%?es&m`TP8Vj)V)y-Fc?-f%UH3 zRl(o6b{HQmxRxCs%|o+Ld2c>G+6V51rlBcl4;1TaMniBn6zgh6v94xR28iRMi*Cd) zKDq#%ht5G~p)=4rbQ)TNPC={CNoWOHhL)fc&?2+|%|o-$473m03r#~)&>mEJd~^;h*ZKJ947d)RhSs1{&?_J(tG2Rur2xAY{<$CSfXGZ>(q+9%NP5nBOjMs0j>Ff}=QH*h)MK?wytp1*BOmX~>m%of^I1pv zoUT56JiZ)XpT=?Fygo#c$npBa)2$ck3_k4QjZwMm#=H3J()ntU_8sp^fu+61yV77O zXS}Od7~{$VEmR=6v6hg9@=H36T10bQS;u27QqFi+5iI45cTIrPPRF}SU@2$3s|@Z# zcmNVC< z0N0$3wdBE5;4HWb&VVPuec%eX7hDFX!6k4CJOSlj{Cd2 zXxoE&b{ z|IQW}_l#jY*V!iHsrWeT35+M*xCiBPy|`(7|1kCv$uD|H>c#88-FoyboGJ*S4bt9k zp?-wBlH6ut*RPO;b+*Ywv$It?8Xm{8rTTIj?a){!&MkGO>zy0@fRy9=m+y6*_>1XJ z`9kvcGk#~yoxjeGeXb(WVYCP46K6iJ{*cQjSHSa-f?T(`f}3s!xxylqPVH5A4!Quv z^O?dt_!;ON^l9iU^eN~J^hszP`UG?u`Z%-(eH1zceFR#CJ`A0NJ^-yi?}wJ5_d!e0 zyP*@%yP!qr2($nlgyx|Kp;_q7&H2%Embn8ny1G&zd z>$mTA=P_5FfXaO$SC(-`t~>(&0(20XhaQAxp*KS_(EZRp=su`iPr0)6$GLJE{(GP) z=x%5abQ?4Y-2x4vo1op$jZm@MTzMTh0d0pmSz5n6ekay#V;xZLPORI$^UT%{FRk0g z^H0BS`2;UsAQxY^%{4mH_e!0C{NKHQ-rLzC?>pk_q4_~ceBHK`gLT_}om1@jH$VU9 zQDsQm_r7lXUnmz^tHG5ZcO(5f2JaqN^8)L(<=-}zzBlCGzHVE}S$c2h*KLow>YThD z?pE>V=kl(eXS{CvYc2yWk6m-!_5|7i{R;m7)UR`GuG>aGgmvD{b=$aKU_E{m;l6=& z`OS6P58!&LIE^CF=DO{t&>qjAedfTT|Ie)3UM)9Txl6k$x{njBvhVLZoq>#7Ui`Xk z{NLn{Nv2Z2;0&}6iuE|7X>bb4s~l+jIEwW+qaj$% z==i7sV?EBOGXsjh$jL|-p!3i<=qz*wT8Bu({&IY@3@$+@phai_nulhg z8E7B07n+8qpgqteG=z3T4Kx9D;?{+%qFuj!o4!xe1&lo?>nd`wb=#aWCzrQN$31{w zPtE;EbKN$z$Ahl<-1k8G_2b+xa{KTUtg*gX&Ik8LA^D$foiw+*UMJmLw+*{)uG=Q- z;C1R1r{i67PH7!3cph8@FMy}Oi{Khq`o-qDZLDK$uG@C^&E~pocX_ye{BGJ^70k=J z?e3&pKV6~dOQm1>_glYxi_6zP&+2Ts+41=8^1QIIj`iQVj{645FN<~DS*+vE!v3>Z z$DPGG?kv`EXBVAajAs|1^UyiyEOZ81hfYIl&?#sYIti^n%g_>Z0$PL?pm}H(nt}E~ zd!cD)3fcorLPKab)Ibx^04n_^9Y5Mn`q}a99C#Kw1Fb`+q3Cb3=!diDpR$z#X z7P;mMn(Mix9bV}F_nPauA9W3tD@;KjfmWdpLnomRKr7Jup=IcO&=QpITD)$30(uv; z2pxgS1)VDlg7eUW&@5E$L%Bi*ydT;J-3RT3?uDkId!Q-kZfFm58#D>s0u7;?pxw}o zPy<~DO+eeBPMYhvo9nsVeZ0Az`z!8(7>fSYY4iKIzkv4mJG95=!Ow!905{ijb3-)0 zkNeZGhu?SF{66lFqCI{U?IACShN2p{jPS?69|8Xg_`~2|1~=Dpb3+W_`>~qe$2|!9 z_%Yartg9W0#O|8k$1VTgKNP(m?Q;{_YXU6e^`Yo};2RPC1K@Xn-wST8=jMhO!uRhr zzmHqyX+zPwU?01j4n<;j&F|yB5bbd-+GjIZ=E2SN+%i9JuIHY2c9APT1D%6D4V{HP z1)YID39UnAK9Va>gCB>=cq>$$%~tw8Ss9&+No$L{ps!`)oZ%`N4>S2$-TT*LYA zA1Rp+-?Cz zXV6^F%?3>0lT54AS+Ops`F-5n9L@FI_&)CDdTwV9%hqG_$jPtA9&3INxBI^xy}rD$ zPF?1~@%hV2-*d|^)SKVKU2_IU-&^c-ylWaf0j`5f;2E%t)5g1GJkngxjrEsZSvD*F z9(JeA@8OpFeDiy_v2M4k=|7#0; z>KiSA+~I=Y5qh-C+aJjzUq0kkwi#z&B>bc|T*82Z+{MWLFQaW0doEu5O0{6=sX<~NNM(rUfA0xhM z!yV&U#A(_FXgiy>3EB?Rb}ntxv>l_3-1<)Xh}YSlGxA<`Tt08|Z#|zr;FiS+cmOD_ zm7n(CNgJhW=U-6ZyD}deJ6?Ih`)S%fiv0=Fk7IwD^a1R1*YR1D zh$6WDWfSeQeX?Ww;Qf#{^7nR5xU8MIJ=k$O@1!kF8`pI=Z4kqtyGVzDbDLDJWU&4KfK>ZoBZcakl?;(pJbfaL;E+#zWb#fL(DGT z&MVbDMe!zRi`PApyw+bq{<2FubY9c+ag02;4f#KSR;v5^DJ-P89G~5bsmB{B-UMy& zdfY?#kXwHheaNok*1b;L$FlS7kC8%J-@HPcSVpbA6zAiVaVu4kzu~@0o3{yn3?cGa zMREB0WLvo!eryNV(3Ym{bCj0LpP-Fx;w`jI)8>zd%YB?Sa_g_957~A1weLCK8RYx@ zv3%ogei4^S?sR<{aeWE`W5n8L;mbeS1*6>TSF&_-1@iC zhp!jyw(h5omr_^(5g(|(E!oZ7veZ9gPWIjkVqOa8nc(snKO z)3pC~+V3ZwpsgSK)3iTG`&m-Xc$D^UrQI~`{{ZcC|2aYXAENz(v_DPzaILraJt{70 z?62i(2Cj9Kc0NjJ$+d7&ItM-n*WNkuF=SzC8sYSoMc(s@ICt1c>qe+%rJdW+~9YJ zsoJjQY}f3#4ZGZ45QL-`#`Z6c?Y}ywEzjJ)(@ZiAF=*U129WMsQQ(R`MQDiP34f~9}_U8wpLO_Xb9i%*>LSgvW=)iFQ zZ39OeaOBuQ%FzcE4j=62DsvRtUltI9W5XjZT7h5Mv?SZXFmxshU!kB%OsMp-I|GB|qFRi$tldFGiez{qym+nx(3BwQ)eq$Rt`jf5*6W_StJX)EWkEO$Aa%j9C%o)6X>I~raQ zQhEJ+UIvdHyW@DFe_(LnNb+Ks+_vyyZmO+s2-XY_j2s_68d8#rFAgs`c9gsh9}1J3 zIh>BlS!nW_ckGvI@apTYyY8B+_ix=Atf9*-ymMgq7!}n+iRhA9sZf7a@j0cEIT4ra zilJnbSAYMl#}5yV96s8AWZ;M$7)g@%wy5{|}cNH4vTPFN3>MQ!2s z?Yny39ShpAENCYO4G%;I`|YvZ9nryq!;*KBPNW?PM~@vo7+$iqk=2fOZ;NHT^WDCp zWaZ(NzB*Ei#pv<>Oh7H=fmW3xqT@YI@&dSYUq-` zb)etX?6@6pwW6arUfjl!wuPL6%ckBdr0X6{d)ok+@bTecGWve*5k_u1d@#w;a2EYJ zKVCRUy%Wwknx9&pGTIiprhQZ2oBOZ2?j}n5-cw&y#ls^3WxDJFAipIGAJO(75A@Zs z$8SACX$}n^JJOF@oMcL9ZYpbAm?WE$b8+~fZ}{bg=&aVYIvvIf*qa=%&xhi3x)rV+ z-}hL)d=5oN4i9pZC#mn;O6PAY+YN=|tKZOM`*75hADh{;--#EhISS0R7 z1i2TX+uIAa0>xQ=YB!S)9XzgqOE`~K)UgCDHpw5u0!q>cbTpV82*LOqz4cEM_zwg?;(qC{JZRfJ7 zP*h=!^W#dos#2xIhnf{NJN2a>UU_A>YbQr{y{W(cm-YGab3{kLC2{|K$~y9Cc9rB% zF%{Rv!7@~(;k&HbobdG3a8^7pv@MkUsVZyej{kxuz>f;(5d0m)9RvAGvo5!1zKc-M zGTY~<&hoiHvU5Lvp|Z7&ld+_@S(j(Z7l|Zwmk5qut{0ty6vWLz?SmS+3crZf;c?Rr zx)X4Hxf1UU2L|mx_#)fZjk=JU&mJc`*&46EVZYRhug2}@rC9i|ou4|}&hMmiz4`Qq z!x_>UY*m3jIedDtHI`(U^XO zyxdKiqER0uH!j+t10x@dBKzHi-T(<)eg=3f@B;k-CF5Af4TUpqQQU+N@yNMJbcJT2jgO%b_5aPRwpOd<_$IzcxrU7DfH8S~}4r1-T*;7a++S!+eytv2BMJ^K;phg?W3zA_a~ zHl|cPG^IM-bZe!sos_Q8e{)xO@_h8FtFOMM&rL`D$>&p^q&{#f&!Fg#y+0esl0S`X zV?jKbJjC6aoFIO}!#=Fb8-}}+mD(j1wnDQ|3~7~9&UJVk%vGkUQQl`8Mj zEnO6JC@#v9$MOb^8Po35n%eHA;r)M{tu-um7f<`+S489Fo}!xZzHJLnnTzOM;1+tS#H>9W0Y1&p#v<7MLAo04pTitt14re}xnBR+V`u7oc&;#u};{O!$<846^Oyb-G zeRBFoX-m}Gf=TdSar`ISWQ_ss|08X!PqhVelsD&pK0WAPe>c4YkMTO<1@Pq@UJ8Q6 z7_TD^C?8JWN8uOUM{NQA2yq9!Y~s3b_|Fq>*h{}L4*nwXS@e)Q4gPcDP4sZPFUD=e z8Dh@kEIMcFo^1=VG43EPfT{I7mQ?8NhK zVm_x!5r_}-;yhr`pf@pFd)<^_eE-{I*d1#O`*tR)M*X)2G^lMGC)}_TNXF*+Ug0gJ=F(+BT$H1AZs% z!(Tz+{B4z_r-Vs zx34Xz$M_uLnHYBv&w_u8!;}Y>z4NTb>h{v)*w{e174u;HPdwc zfRnUXZ}k&oFW}3G+v{X6baUbM%@V)lNwOF4y&OJ6ObZ1#{P&0xPm%qAze2obwl%0I zu7b~@g&F6}wFY&?GvMnfyrWF^5aV^kb1~-ddGHa6fA#}pAK>>hSI9nSfdSX=W5nz3 zC;I^V_U;CMhQbq*WDhZ3O`Hb1>ushb=u_!4;IC5pwNJMM1+ZC1^`C1ACWymWe^dcq zz~OZM>)`8|A8rk1z^=T#bpBQPdGI?a{@Ok|-=XC1%G*!Y7gq*^N7!)^FIr|g7_Rd|8w9&#B1pM z&V$D|oCYTg;16^7Gi1Nu2bt$v>1HnVtr2f{mhK-hUPEla{`f-h48?CEPf&Q*Cc1tVPsDg5g;!PjDe#|C`m^Z7PAjg1SJ4~sjxA)L;4b2`lWlY( zmE-fAi1Aqzo&;Y_@z-o?bK^<2AJ2UVzk~Ddq56Y=iFn;^>TeWRV!W2ZYcb~d)8N14 z^eMXD6wk$YErl%+valH>mlbCueEtMD!w+qXX49!!C6Vy?EkF+bhHoa1rU&yfEC z8pP1;%Z>mFbi7f0Q;J&sV{IJYNI*@jP_}F8|$>|GH;_fVzIi`MC~ylud~yl$``Z>NcUd$v-0@m%V&R7ZB~KTX_|Z?rS>W@6vY zu3RH)?KwVk2XPYVpQHF4G+5dTN^N8~?4u}ge z=5RhQoZqV{{<wg~&w%~BXcp|}MT=lR zFG|pOm-F-UB5Hyq=6Mk{!P0qINAnRn>J$+|wS=kl2j}{CK^an9K9wA;SH5Jq7mT z^)%Rz*LnWQ;|o6@$kH60+2>yX`}!BbKL0Y<=U)N){HHM9_45Hgp7!$rKc05u1)2}= z_?eH#yE&xy^8r78_Va-N<3~RqNW_@u1AaX1=K~?anRz~tj4{s#{P@|IpGLT!4`jf8 zK9G$u&jTpvFlm<0Rzz!ccGcMa_412Zw^`2df{IX`#3 z&9npyD*YnZ&j(B>@%?-tB#vL7DX^apsW{cgL9L18J}?kDvGQ`SkOFjN&ZV z&j%*Je*9liJQ-u24@`so_W4+Iy>`SbIEM2vYpV8DJp&>dr*4}@Sp9|)6@pPvsTFA?_hfnKnm5AZX7 zx}`YBd-1!JljaANM!UQD0kLoQ=KO%#dLNC;X*|vC z_+MgvK<96o>dSW0oFCA5x;Z}xn)3r0k2dEA^1h%sKal>>k7t|ngXQfJV0`W81I_t? zw2z+;H0KA>9{*AE10H|!x}gqIo{Qf?`f>T+%7Ew2%wGb}fH%fXuJof(2D2EQ^w62XO8OnXb zdC|OB`5$d(4_fb_l6;ZI!t6iA5_9w_mK?p`Qt>~Be0V;hU7P=go>;&$F5W8l-XP{3 zd>sD8xF_uw;IHfR9{5kH_j{|{XK*90|JP9x-_h|lkL;_fk&o1s1m=hTPQag^ z|7h3dzCmlb@0_dW*(cfCxXb74lkDvsu6@ov$=)`=e?r;M7hL_%KFQwhMSN{+TN~2 z{k6S)68UI*qa{ABKHA>?8Rt>kTPNacd;2owvVrc8-c4cmG0Nv$dg@j{KnQ&s{QZ5| z`~Lv^dsO_NB;F9apU$A)y#?{To%nqC_v^XbvdZTH_)jVS&%%F3`EQ3mzc*(Wx=$K| z!GBWuUqbEAKAuDP^E&kn zvHMOR&dY_)e+^>MdT{hBms9wLSiixqMATqp zn{d9ee*W#WUqrqfzMr-84N^NqCm>zp}5 zTMG9RW^SYD7;}E^fjkL^^LN3da6e(@?-eRyyur-h`QyhQ%>2Iq-MBw6-$Gj^#{I;V z7-xy+V;m7LZlMoyoSu)r0(xP2npUZ}knXgvTs>Nef^dOpUSK0)ud*>O0x@5UJO`3Pgo=WAPx z**;S-X8YV5W46z}7_&Xy9Amc6e2m%tMqT8))eTuV+3yLQcmlaPco>Dxmct-J@;swP4 z`cHp6MzQZ-eK@aE^X#` z;+o>R;#tM>iWe0pFxB++?^c{toKoDYIHNePxTv_KxT3hKxTd(ScvkVe;zh-Ywad?6 zw_;wO%g(n?N^!5^jN-iFqT-U`isGu`n&P_RS;g~;7ZoRB<9EI^x)moCrxf=p&M3|+ zE-Ef5t|+c5t|_i7o>e@rcu{eDzT%EQHr{7WDo)3k$M^C12y<427Zk_m9~{4|!Y38S z=N}w@T7}Ojo>RP_*gptjd*=KM9t?R7756AkEACUARa{U!p}4HL8sp7WKVFZ_j_b!< zS3IkDUh$%0_r=Ds{JQZ@*XN&9%-e@rcu}$Y zVUO7HbmI}BKfa{ml;U2+8O3?U{2kToeEucH6~$G>HN|zsvx?^xFDg!$<@M=SoK&1r z+^aaFIIp;#TCU>#Wlrs#j}d%6)!4wKTH%qempN#`;+o>R z;#tM>iWe0p@IJ(!k8Z_D#VN)9{gqFjQQ>*TMa3n>6~$G>HN|zsvx?^xFDg#peUGny zx8kH?|31#g?^WR$#d*a=#U;fR#Z|>M#dXEAisuzCD)#FE{PA?-eU|5>V*h^8hx7l9 z`s?Slw3Ag_P&}cS|8F#&ep2z2;%UV*isuwBD0V;ELj`jExxVJ5TzZ2;#XXACiu)92 z6&DmwC@w3WR6M1)9%Ft#GOKuA@uK1ceUA=1K7LN$tvIPTrMOpdMlpYH4?CZKQE^Fe zMR8SeO>tfEtm1jai;DUGhU4|?R-9CvQrxRJqd2d)sJNuKqPVKKrns(nR`I;zMa79t z>i88W6{i&UD$Xd*D=sQ7DXu84Dy}K6E1p$6uXs^$f+zXpynS{nPAX0*?p2&ooL5{_ zTvA+7Tvc3CTvt4+cwX_M;sn-%EFHh%q~es~Ud0*3dBuMHi7&6D!YhiaiffANif0wi zD_&Hbz|b$GaY}Ko z;*8?F;-cb`;)>#`;+o>R;#tM>iWe0p_@NoOrSq>isW_#$S8+yhUU5-zNpVGSRdG#m zUGc2qdBuy06BnxESDaLwQrxRJqd2d)sJNuKqPVKKrns(nR`I;zMa7AW)bT6k|3hQv z?IWeQS8+yhUU5-zNpVGSRdG#mUGc2qdBuy06I+%aU$^3<;*{cE#r(fL?AmF218pNQ z=Jy46E52Xx!-^kO{Dk7CW6Y-gtm5YtuX`m$BG*nE$KRxQo8rAO=HuC~_@Lqu#dj;d zU-7&82ag;*R=E9+Ti$(hbZahu@U}zQfy2S}k%8h!uzh%7aQmC~zj-@DO0?EP%7B*<^4P1Pa3z9hUM-) zwTZ?f#1qC$cZHP8Vo*(Y^zY^hlQ^a0bV|nw{~gd>9F2~|DIJMZN(TR3@E4_K0gLYL z-zm-Fgc^^jM}+clNJTrPq7h4!@`Ar883p}#JlXwp2L+J(HSV}$PJA04%)DV4 z&r(2oX>a+C$}adP3O-$W|NkLA7c3X?82kh6t)VTw9JfufIiWjOPpLGeFo|0R03bV&)`px-m}-#2W9VLo4t>y zzJC9Z(x0mRvvWv?^4b3R)u%7tA3vWHL_q?PnMXt)#`w(#>hjs9Pg(w7NQxe$=kod0 zn=YS!*S>AvcaKrf1Z_*MjQ)?)#htF}?~+GrJOcKMe=IwGy%?u^8*RRPJQffB4~@5E Ae*gdg literal 33344 zcmeI5dyJ#kdEO5>vm@?mC5_kG(KxZ2PqDn=%Bx+@?#iZRX-#Rh5*@FViL6a&S1vir z;V#FT3q6-LX{soLr~;cR4Use(HZa<;lE6e_1Ovx_m|mc1;~+$v6w}sd=_V+~fD#Ol zBA5U{%Kp))&wI{u$dB*LY^207`o|pX$LIXc{q~*ryO6X0@XFO^qLGO4E@J+-8ITV( zruOo{pR(SRc>pQje87djflPP7oBx5{+Y<8T>n{ARs4=~_-+p^i75a}5EkV~<+Y$2x zo8gO0cQR76{6@@*$^Z1bEBDPYm+#t`EAWW<`!=BZY8)*xruu3?ourOaV^l-!*#fGs z?oxNC+te;~i`t=XQrpxGYKyu~ZBiT5I<-bEQ%lq$HAl@*r>SXbikhS*sBvmQourOa zV^l-!aol#PJJfAzm%2smP&cV<>ISt%U8gpw4QicQqn4>9YLS|wW~kHDG&My{QWMlT zHK0yX$Eh)@6;t^l!zakgfr~%o(p6Smep&x=8a?vhh>aJP1(cs~^}Qj0u#+RBHvVMP zrF(P6qPYukGDC7+lyHdNi=%q%ovr&f^GFQ$hAZCYmnz?|p~n0IwekSlJ?Z*2sAt!n zw}12V*q%1VpU2lC?nDgl2fGLC2Qnf@%(EB;wEL)Quv?wZZ^Kc18OIxL_-sFa3K4_z z{g_Rh|D|^}Zhjv+Y5t_&e`&xUxZy#2c5Ha{cFA_Edb>!?Q8UzOYMPp&CaDQ3_n+GV znfuRe?mxG=|J=6A$5e0k?08gf?^1WD+te;~i`t=XQrpxGYKyu~ZBiT5I<-bEQ%lq$ zHAl@*r>SXbikhS*sBvmQourOaV^l-!+4)5OsXNqdYL~i2?NB$VZR!TKMO~*hsSRqK zTBDY!C2EnHqh_en)HF3kO;QuoI5nV7Qpc$=sujDwkHA|UV?D11HX?uP{Z{+uEB7aV zKEEl(7*6;;9MxN{+%F+K0OxPHjUqpGKggIb;RtZ#$6R~D`%)3%vVTbnr97`6gx}XA z?T{Y6xq=V4``+vH&96F@{Y|a|q#S99l=DR#m9M(bm+9C129W!i4enM(Te~~|c-pA{kgZkmy>C35njqSMWgcM`Tkrw%M@4h{5exyCe zQO=#(BmMF9`1TC?#d&=liQweA?4W%ZRhg6KpW1X40l4af%r53D;>Nc+ktDnEs!pWH zuAb^d+VM=>>a_?egsVgX5tQe`XChAX6FD1RiMV>I6J@fir#ew1r>s^d>f|)JL7pZz z$r8{LM|SO~P87+m9o31FXS-0qR z$@J5VryZS0lY6!v^oP7lc6J)$K~6A!n;a*1$*x@(Z?bC_=7a3oh4~`8c2y#6vTIi* zvO#w3szh33*RD!ro$T6Gi8RTsU6n|K?Ald{)XA=0l}L^3+Es~^$*x_MNQvCGT8R|N z8{{0hMb41d$z@j*>rRfi>#Fee*jv1=wAVkZ zU-~aY~f%hlW59}n-N-Trr*`{QlykGHu$-sb*zyC=&W&l7g3 zJJfAzm%2smP&cV<>ISt%U8gpw4QicQqn4>9YLS|wW~kHDG&My{QWMlTHK0yX$Eh)@ z6?=Vf1l~K{M@x?U;eE8-w-4{52kSmgIprF$z}2; zxkm1g>*OtRgWM%I$=l?0@(#I0-X(94d*n9R?T3f=(Y&8HypOi_^YA{}o*oC^M^DDx zdF1b>-#6*_dv-tV-p~5$-IEb_e_j0ouc!O>74Po7&fvcKd3XNjc-@%eeRYoKL5}y; zIo?<2cwe3Cx$CRkE_H{xP3=;*s2%DiwN2fiwy5jWCbdDWQ)|>RwL~pabJPrVnwqAj zs7Y#q8m9)-N$NN?Mm1Eoe^zsDU#;fcep}6Lb3D7$Eoz6lN#(wq<9?juKAl@ZH>exiN0J@>RF)s^c*i@2c;=XFR;WKD@t{ zg>m?vn)~G8duq2&9Nu5Mad&ytAg9Q6a*|vlC&*>1 z-|P3(Pp{3)2cQ1r3+JAlzG@BU|7Rcn@=qeh-6sEAH*Tg;o*EbM|kbVTYTZ6Jd#!dQO2m;oxRToK>rR7DKCZNVH|Mx zqG>LJMH6-32(>U&uC$3RD&MW58%o1INmNw2JLM9^@%H>y%#aTue~04jatR|#w%?*^xE6mZ;wqlRM+$9r&W;#k4~ckfAj zgxl=r48cSF@?|4D`UCi&8%krpAmJjS@@>N}<3PSqc>`C6-@S=7=4a?nL4S_^8uS8RrxZ8CMz08V(s(S*M#g{wof+dmqFHixQ4LB%jU=jhSD= z;rc$vgwp?4C|vg=;9VT(+h_`U43TG{;wIpixsY?yY#wsc!+EGf;Vsh=0e=yJ-20%K3T? znWP`m#=l8F7EzA$sfI&bxc-aaWyDMUAAx@c8xrPWG!6d({L)TwU!*^P{}%lz_-pWg zOcaOgv*O>x@z3FZ3@QcxGW?Ijn}Yw>;g@r<2LHc;{}TM0@Y6+;-iNBWPf5tJPlUp! z;pcaG?XQ6_2fhS5-cKMNU9$81tB8c(?!~_be+uE^egpoepaG6=FgykS8w}6E|8L+& z!J|^vZ^Qp2RNU{v4;Pbt;rCUV%QniGZ->%I5Xu>v^WVotkFeuUGkrK-=H!oY@=5$N z`^3wdc^@`biBInnFZur+ zOumq{eaSA*d?~w9S&<$VmQ8+XVPR=8Yx_;VYXG6NTqrD*R@r(VI5%tX56#8M`0-dN zE-kMb+w*>yrTl8y6lWG^=L>^+QQqQWA-`%?OXtv-{LK9Pig;YB`mq?}!t&zG{JFyQ z(v5TZbBl%5v+$kG8^i<$6&hc`=;c>~1A84jj5eK?GKNZby*uZo{A|%2U0MvD2vA>k zVWyOwUs`%;t&}ay7Z&2DIIw4eQ!;X=KW>gL7gpDn7XxHDbt-sxX%RtlH-h+s5|3Wl zd5B;6i5J{TyZmF%J$L2u3#U(;qgYhImkY~Fs49U>SQrOY>er4;EozobQnRfF*-%zC zdwp$gesyj!yHHqIDXhj3d?rYo30CI5Tv)mhe^`=99_S;NFnymA{wxd?;#a zDC)dKEf;2Hvnxyamu6;XmtEO$OytUHaBFF9HhB2-ps1TR7oNZN+~w?(*D|PFx+(R__@Wf__NYuvX?f{-A!}Q?KypakI7b7VkQ~~Z1+3_`cJ=1mY+RCY7X6&Bm1c1ca?UyY z7M)bumiC!hN)vi^hpPqOmdszIScCji3wD}2xT4@dgutgKyMK%N`ROAA@H zV$V|IaHFm>K^$w!&BffTANb*gXjiQr^#X@vd2aFM^|c!qNsQvH0+zVl`36g;a2hMA zUs}OtmbL3fRhF*Z;aJ?BGiI;{x&iE$WOLcIyHZ)qXKxf_d&G8;#nfSSVbeSlOiAiJ zi@Pwiv}1V&@sjFjAO8B!CB{BZM1K7EAew zU;r*sMhw9s2$1DulgUasa5YJ)wYga=F190_5)oOy>};zgk)64@Syt&XBKM_B!G-fK z5X%+mBm-hy5K8h{U2QJdX5xV1f7z!@Zq|kpprvw7UjDJ?uVkOU^5oNTX$kr@ln4z>Ja)kxbuBm` zOQ?;0t-AE5k$DQc4+g2^W@ETUm+DL)eYQ0{icG$8?`yGsY>0LkFnz|3op=i3 zdkMbms$5wZ=X(jE2ymZ?$Id^NaE(Lko+_oxGeH4SXHkF~2cI4V9F!hWO#cq-)A0E% z)!2EWwE;WJ;}$7G#nAZBseb7BP$-u^(q0IKUO-xF`!Esqnng^4_xp4Q(u;K|=@jF@ggW}F3-@sPve+l&D z<;z#5?G=!pe3|k%_RP~_w9#cBE(@d|4yzuDlIxcnvJKj_cCsZzE}@49Mz)@V#w8SY zz_1{N8F0n z!yFF}zpu#}OLXL~xK{JY&%28xxuhB%GPyeDm|Z;JI^B)v#r}2E-`;8(tjP;K*pS*nKxzAiNXK`_|V&>=ag~gSEk>|C6y)`su7AnWncsSU?@i=ZIPoB>Pz0(h)sOp)>bMEIK{ zrc8!dSHq{||0Nu;%@MOs{yj8LC5gmCLsSa=!vKC+iCJ|Lhr`IgB1C9pzlZLr$amf z&VZ%8e+E7N)`-c4cnn-3qb1gr$&;AlqyG#22TS`t1CBJ^+{-fyaT5MDgkS!;TPL0` zg2xfxuNO~&CPO?1PBK5lx)eSo{V5zWuNktRS3hrlUNMz6{hy-#vGGw;BSWm)z^9aV z3=dVtno+Y&eq8t~QTq&2;-3|MJZgH3hd776N&Gd$A4^BgB>7cIe>H02c)|8~^G$nv|ZqkkAR7&06GAB3@pWxgf-cflv#ikcwA zN5OHj?_ZMqe~>szq@>mT0pByn= z#oOfbh#z}D21Div{kaUjCm1o4ih~f}jrbI~g!D%r!g->&NN!5`akQVj4L*Km#IzJ| zg!mZZw?ZuGyX0{^@I9UwF}sR;AwGuq7{*!p^BB^{u8x{G`387wdekJyCGdM{BPJQ* zV_;b~lK)kSe`Um^LwpQ8P5z3+*GEhy#K*un@;4;@wGmSc@iB0T+(G=Y2IfD+W8fOO zi}?3qGpmRAIJiOnGsI6cM@%!s_kq{R?}4p}eg!P^fd2f1@H)mHD*T#o2Imv`8^SN* z{DJ!YDT@6`Y?gnvD&bMstZR7ni(+j$;g5l3AM^1a04K<9lfe56c%j$Sk`Ho?Coov?8|GDy?xywd;7Xe_V(3aP070QE=KnDH6VNYnjm}onj(Aq)8>Bf z?W?yJ!eU>&y)f7}#J+AZy|=I4UU>Vu!}t`^i+$~py?yoe#M{>x_h)Zk$I0HldVAyT ztG74azQ&neSnO+p?EB~Kk+-kYjQ94nrqb8R-o7>!uZLLdYe(hZB76I~t$2s*?Q0C} zmihGdHBcN6vDnu%+1uBmVsAgZef9glx33#a@3|dfv9H|_i+$ZDd;8i`EN{Z3{Sq(s zb)4+&Yl7_UYm)5kYbwNIU(;l7U#CMX_BBKH_B9t`v9Cq4x38rTi+wGVy?w2PSnO+^ z?ConK#A08YWN%;BLoD{SMfUc!g>jMb@%D8C`?#>TuUlkqUw6Q=U&($REk^7;pa1@Z zgiqt1FJBw%`@+}2-(9k|zhY0NJ>LF$dusP_*jH~)?LH31rKW9< zuMbPrvbVPxmM7yG#dyiR^&WfM9E`iQw_rc+wq6()Kkl|(@S(kR^Cb57(B9(y_0Znh z^UmAnLwoD?A#aZl?X4RRvA^GUd&~V?p3CAg$7G;lH@^j&E^eJ1jX9QUU5Wn$IgV>P z;dyciEZ_P1ALKUq82Tno?&+kS9P{~lT4Z0(F4@P#8$f1bevgz+KxlovRzi!LF%RYw)NBtLux5I(-kMzGmJ&1hC zrax-$vj?Ggj>7O>I1v6nw(U7;N;ZBF`QI3hOS2*OYYg8|;X5o}uBXH9Uo%|pgTwA8 z87}8m*p1nBbJWDt&{bJ)OO-FzySNjz_X**0#6M!cjXWIs4V(V%J?rgX*!JALXWjls zhIfXGu{2`8p*S2dYt!GeXZ(MW;d=c4r)|$Yd&d7iFkQZ9zs>UX`2Qxu_4vEL zdwP$3{u=JVU$T5X{woaEHj@>ZhP5Lg(o;+bO?aI1xI(dR%u?=Tt9z^rG4!XOZ((G znm7rT_DypA2;1}=Z_g=&ixZadTE`(ySlZ|9(0=Kqyua=CrP+R5q8RDl3n7;NS&yU1;PAX0-&M5Z#vd>>u@pZ*b#Vy5c#T~_6#XE|7ieu8SQ2*q) zSeWCAlZw-d<=!crzo@vZxURUVxTUzQxTCnMct>$hag5j95-jUc-aCl%?61o`Cslk} zaYk`baanO)aZ_5wCPZ5rnd)6@5 z6*m>P6t@+36n7QxD7KS~2FQGheHxcZhw~gLPAE<(o>rVwTvA+9+)%u(cti1~;w{D7 zigy*8*l>UOXO{;3SMdqODaF%@iy;T!Y;<)0Z;N^L;NAMe@Agoacmrk z;H1Bjp8p+PpW`Y%sW`1TqqwNJthlbYsko)Mt+=DOt9VCoPjO5x^5FXYR~%QIRGe0v zQCw79R$N!yRNPYBR@_nCRlK9Pr#L2mupr!j#c{<+#c9PE#YM$s#dXC^#Vy5c#T~_6 z#XE|7itQhR3HSfKb~yU$A+9*7IITFNxTv_SxURUVxTUzQxTCnMct>$hvHb%$;r`#R z`mZ>tIITFNxTv_SxURUVxTUzQxTCnMct>$haZGM1;QHsk;<)0Z;ucW_U@k5Fq53v+=Rq>08=M}%K_%+495@NAG-&Fi9 z#ot!^mf}BG{P9mbb@}Nl&!nEb^u*)l>}sLBYR)bf=FdL$!ZT+D_W!AuO|$Qh=iP78 zhO&iz$+myKaDu@P)rZQEACmb$S|RP*w{D*x+-6(0kJvZoPzwIR5%(Ll@LzoJf7!#F zou9w8Ais`Z#$O`o|BTK5sgJYxZT9NSb#r#5vS5{CY5cF>u0HkDquGxc$OR`;P9Dup zC0(e~sq9Au6HXq@enjY^lM7DHJ3&qxd4W1by_kJe@|<^)aPnyOybZlTMdC;I478iW zi~CPj_$PgP2KtUUL(_awS~iunf+kr-lNdZjy&$O&Z57evDYDax+4HWOR;C;!oM32d zD2B!=cuEq3t)ll<6I9fdaPdwNp1?Wxy>RlkrTFN0sJPjR!wD6Mwa4nB_S$EEtd zVUO%zVfROXJLUK9b$uQ__VH-G3!gj+N%cdVr59+K%SrR=2-~mzUH03* z_jRQW@_YUoJp0w($+;91`(LF(0TmZa}L%YarN^y z-vK@)ZP>}*VB0T$lldFr#PIw2eemC9e$QUxXPs|@*C9S!pTD0${{8x2yzX-3m{I0m zZee`=e*9%lr2X1;FT0RY|7Ce5(Dloj-mm@+>u>P7LPRd1b^RYgQBZ1 diff --git a/internal/ebpf/bpf/prociter_bpfeb.go b/internal/ebpf/bpf/prociter_bpfeb.go index 1f27cf6de..7c35590d7 100644 --- a/internal/ebpf/bpf/prociter_bpfeb.go +++ b/internal/ebpf/bpf/prociter_bpfeb.go @@ -13,6 +13,34 @@ import ( "github.com/cilium/ebpf" ) +type ProciterApproverFileKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Path [256]uint8 +} + +type ProciterApproverLpmKey struct { + _ structs.HostLayout + Prefixlen uint32 + Path [256]uint8 +} + +type ProciterApproverPidKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Pid uint64 +} + +type ProciterApproverPortKey struct { + _ structs.HostLayout + Gen uint32 + Type uint32 + Port uint16 + Pad uint16 +} + type ProciterScratchValue struct { _ structs.HostLayout Arg0 uint64 @@ -75,11 +103,21 @@ type ProciterProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type ProciterMapSpecs struct { - DropCount *ebpf.MapSpec `ebpf:"drop_count"` - Enabled *ebpf.MapSpec `ebpf:"enabled"` - Events *ebpf.MapSpec `ebpf:"events"` - Scratch *ebpf.MapSpec `ebpf:"scratch"` - ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.MapSpec `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.MapSpec `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.MapSpec `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.MapSpec `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.MapSpec `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.MapSpec `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.MapSpec `ebpf:"approver_mode"` + ApproverPid *ebpf.MapSpec `ebpf:"approver_pid"` + ApproverPort *ebpf.MapSpec `ebpf:"approver_port"` + ApproverReject *ebpf.MapSpec `ebpf:"approver_reject"` + DropCount *ebpf.MapSpec `ebpf:"drop_count"` + Enabled *ebpf.MapSpec `ebpf:"enabled"` + Events *ebpf.MapSpec `ebpf:"events"` + Scratch *ebpf.MapSpec `ebpf:"scratch"` + ScratchHeap *ebpf.MapSpec `ebpf:"scratch_heap"` } // ProciterVariableSpecs contains global variables before they are loaded into the kernel. @@ -108,15 +146,35 @@ func (o *ProciterObjects) Close() error { // // It can be passed to LoadProciterObjects or ebpf.CollectionSpec.LoadAndAssign. type ProciterMaps struct { - DropCount *ebpf.Map `ebpf:"drop_count"` - Enabled *ebpf.Map `ebpf:"enabled"` - Events *ebpf.Map `ebpf:"events"` - Scratch *ebpf.Map `ebpf:"scratch"` - ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` + ApproverFileEq *ebpf.Map `ebpf:"approver_file_eq"` + ApproverFileHeap *ebpf.Map `ebpf:"approver_file_heap"` + ApproverFilePre0 *ebpf.Map `ebpf:"approver_file_pre_0"` + ApproverFilePre1 *ebpf.Map `ebpf:"approver_file_pre_1"` + ApproverGen *ebpf.Map `ebpf:"approver_gen"` + ApproverLpmHeap *ebpf.Map `ebpf:"approver_lpm_heap"` + ApproverMode *ebpf.Map `ebpf:"approver_mode"` + ApproverPid *ebpf.Map `ebpf:"approver_pid"` + ApproverPort *ebpf.Map `ebpf:"approver_port"` + ApproverReject *ebpf.Map `ebpf:"approver_reject"` + DropCount *ebpf.Map `ebpf:"drop_count"` + Enabled *ebpf.Map `ebpf:"enabled"` + Events *ebpf.Map `ebpf:"events"` + Scratch *ebpf.Map `ebpf:"scratch"` + ScratchHeap *ebpf.Map `ebpf:"scratch_heap"` } func (m *ProciterMaps) Close() error { return _ProciterClose( + m.ApproverFileEq, + m.ApproverFileHeap, + m.ApproverFilePre0, + m.ApproverFilePre1, + m.ApproverGen, + m.ApproverLpmHeap, + m.ApproverMode, + m.ApproverPid, + m.ApproverPort, + m.ApproverReject, m.DropCount, m.Enabled, m.Events, diff --git a/internal/ebpf/bpf/prociter_bpfeb.o b/internal/ebpf/bpf/prociter_bpfeb.o index e93d91e49b93252f6ccb2e1fd343e3b520c79d5b..541573a5db7284d3d4bc6e0b1e80662f2f3d482e 100644 GIT binary patch literal 9696 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 delta 2071 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 W-rHDO7Yr-t-DcnkHMhjOPWu;opvOc2 diff --git a/internal/ebpf/c/common/approvers.h b/internal/ebpf/c/common/approvers.h new file mode 100644 index 000000000..0aa935591 --- /dev/null +++ b/internal/ebpf/c/common/approvers.h @@ -0,0 +1,237 @@ +/* Conservative in-kernel approvers. Default-allow unless userspace + * populated a proven superset of equality/list/prefix predicates. + */ + +#pragma once + +#ifndef BPF_F_NO_PREALLOC +#define BPF_F_NO_PREALLOC (1U << 0) +#endif + +#define APPR_REQ_PID (1u << 0) +#define APPR_REQ_FILE (1u << 1) +#define APPR_REQ_PORT (1u << 2) + +#define APPR_GENS 2 +#define APPR_MODE_MAX (EVT_TYPE_MAX * APPR_GENS) + +struct approver_pid_key { + u32 gen; + u32 type; + u64 pid; +}; + +struct approver_port_key { + u32 gen; + u32 type; + u16 port; + u16 pad; +}; + +struct approver_file_key { + u32 gen; + u32 type; + u8 path[EVT_FILENAME_LEN]; +}; + +struct approver_lpm_key { + u32 prefixlen; + u8 path[EVT_FILENAME_LEN]; +}; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, u32); +} approver_gen SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, APPR_MODE_MAX); + __type(key, u32); + __type(value, u8); +} approver_mode SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1024); + __type(key, struct approver_pid_key); + __type(value, u8); +} approver_pid SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1024); + __type(key, struct approver_port_key); + __type(value, u8); +} approver_port SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1024); + __type(key, struct approver_file_key); + __type(value, u8); +} approver_file_eq SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_LPM_TRIE); + __uint(max_entries, 256); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, struct approver_lpm_key); + __type(value, u8); +} approver_file_pre_0 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_LPM_TRIE); + __uint(max_entries, 256); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, struct approver_lpm_key); + __type(value, u8); +} approver_file_pre_1 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, struct approver_file_key); +} approver_file_heap SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, struct approver_lpm_key); +} approver_lpm_heap SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, u64); +} approver_reject SEC(".maps"); + +static __always_inline void account_approver_reject(void) +{ + u32 key = 0; + u64 *count; + + count = bpf_map_lookup_elem(&approver_reject, &key); + if (!count) + return; + __sync_fetch_and_add(count, 1); +} + +static __always_inline u32 approver_generation(void) +{ + u32 key = 0; + u32 *gen; + + gen = bpf_map_lookup_elem(&approver_gen, &key); + if (!gen) + return 0; + return *gen & 1; +} + +static __always_inline u16 sockaddr_dport(const u8 *aux) +{ + u16 family; + u16 port; + + if (!aux) + return 0; + family = (u16)aux[0] | ((u16)aux[1] << 8); + if (family != 2 && family != 10) + return 0; + port = ((u16)aux[2] << 8) | aux[3]; + return port; +} + +static __always_inline int stash_filename(const u8 *filename) +{ + struct approver_file_key *exact; + u32 zero = 0; + + exact = bpf_map_lookup_elem(&approver_file_heap, &zero); + if (!exact) + return 0; + __builtin_memset(exact, 0, sizeof(*exact)); + if (filename) + __builtin_memcpy(exact->path, filename, EVT_FILENAME_LEN); + return 1; +} + +static __always_inline int approver_file_match(u32 gen, u32 type) +{ + struct approver_file_key *exact; + struct approver_lpm_key *lpm; + u32 zero = 0; + + exact = bpf_map_lookup_elem(&approver_file_heap, &zero); + if (exact) { + exact->gen = gen; + exact->type = type; + if (bpf_map_lookup_elem(&approver_file_eq, exact)) + return 1; + lpm = bpf_map_lookup_elem(&approver_lpm_heap, &zero); + if (lpm) { + __builtin_memset(lpm, 0, sizeof(*lpm)); + lpm->prefixlen = EVT_FILENAME_LEN * 8; + __builtin_memcpy(lpm->path, exact->path, EVT_FILENAME_LEN); + if (gen) { + if (bpf_map_lookup_elem(&approver_file_pre_1, lpm)) + return 1; + } else if (bpf_map_lookup_elem(&approver_file_pre_0, lpm)) { + return 1; + } + } + } + return 0; +} + +static __always_inline int event_approved(u32 type, u16 port, u32 truncated) +{ + u32 gen; + u32 mode_key; + u8 *mode; + struct approver_pid_key pkey = {}; + struct approver_port_key rkey = {}; + + if (type == EVT_TYPE_SNAPSHOT || type == EVT_TYPE_EXECVE || + type == EVT_TYPE_EXIT || type == EVT_TYPE_CLONE) + return 1; + if (type >= EVT_TYPE_MAX) + return 1; + + gen = approver_generation(); + mode_key = gen * EVT_TYPE_MAX + type; + if (mode_key >= APPR_MODE_MAX) + return 1; + mode = bpf_map_lookup_elem(&approver_mode, &mode_key); + if (!mode || *mode == 0) + return 1; + + if (*mode & APPR_REQ_PID) { + pkey.gen = gen; + pkey.type = type; + pkey.pid = bpf_get_current_pid_tgid() >> 32; + if (!bpf_map_lookup_elem(&approver_pid, &pkey)) + return 0; + } + + if (*mode & APPR_REQ_FILE) { + if (!(truncated & TRUNC_FILENAME) && + !approver_file_match(gen, type)) + return 0; + } + + if (*mode & APPR_REQ_PORT) { + rkey.gen = gen; + rkey.type = type; + rkey.port = port; + if (!bpf_map_lookup_elem(&approver_port, &rkey)) + return 0; + } + + return 1; +} diff --git a/internal/ebpf/c/common/events.h b/internal/ebpf/c/common/events.h index 185eea59c..e9df5bc41 100644 --- a/internal/ebpf/c/common/events.h +++ b/internal/ebpf/c/common/events.h @@ -138,6 +138,8 @@ struct { __type(value, u8); } enabled SEC(".maps"); +#include "approvers.h" + static __always_inline void account_drop(void) { u32 key = 0; @@ -256,12 +258,29 @@ static __always_inline int submit_from_scratch(u32 type, long ret, u32 syscall_i u64 key = bpf_get_current_pid_tgid(); struct scratch_value *val; struct syscall_event *e; + u16 port = 0; + u32 truncated = 0; if (!type_enabled(type)) { bpf_map_delete_elem(&scratch, &key); return 0; } + val = bpf_map_lookup_elem(&scratch, &key); + if (val) { + truncated = val->truncated; + if (type == EVT_TYPE_CONNECT) + port = sockaddr_dport(val->aux); + stash_filename(val->filename); + } else { + stash_filename(NULL); + } + if (!event_approved(type, port, truncated)) { + account_approver_reject(); + bpf_map_delete_elem(&scratch, &key); + return 0; + } + e = reserve_event(); if (!e) { bpf_map_delete_elem(&scratch, &key); @@ -318,6 +337,11 @@ static __always_inline int submit_args(u32 type, long ret, u32 syscall_id, if (!type_enabled(type)) return 0; + stash_filename(NULL); + if (!event_approved(type, 0, 0)) { + account_approver_reject(); + return 0; + } e = reserve_event(); if (!e) diff --git a/internal/ebpf/doc.go b/internal/ebpf/doc.go index d283bd6b7..97119d250 100644 --- a/internal/ebpf/doc.go +++ b/internal/ebpf/doc.go @@ -19,6 +19,8 @@ // Package ebpf hosts the Linux eBPF instrumentation backend. The event // source loads CO-RE programs, captures process, file, network, memory, // and process-control syscalls, and reconciles live events against an -// iter/task baseline. The spike subdirectory remains as a feasibility -// prototype. +// iter/task baseline. Optional in-kernel approvers drop events that cannot +// match compiled rules or the CLI filter, using only positive equality, +// list, and prefix predicates. The spike subdirectory remains as a +// feasibility prototype. package ebpf diff --git a/internal/ebpf/loader.go b/internal/ebpf/loader.go index 7ea3dc4f9..cb7ea0af1 100644 --- a/internal/ebpf/loader.go +++ b/internal/ebpf/loader.go @@ -95,13 +95,7 @@ func loadCollections() (*loader, error) { return nil, fmt.Errorf("loading execve objects: %w", err) } - replacements := map[string]*ebpf.Map{ - eventsMapName: execObjs.Events, - dropCountMapName: execObjs.DropCount, - scratchMapName: execObjs.Scratch, - scratchHeapMapName: execObjs.ScratchHeap, - enabledMapName: execObjs.Enabled, - } + replacements := sharedMaps(&execObjs) opts := &ebpf.CollectionOptions{MapReplacements: replacements} var exitObjs bpf.ExitObjects diff --git a/internal/ebpf/maps.go b/internal/ebpf/maps.go index c07a9de62..51f129b46 100644 --- a/internal/ebpf/maps.go +++ b/internal/ebpf/maps.go @@ -21,9 +21,28 @@ package ebpf const ( - eventsMapName = "events" - dropCountMapName = "drop_count" - scratchMapName = "scratch" - scratchHeapMapName = "scratch_heap" - enabledMapName = "enabled" + eventsMapName = "events" + dropCountMapName = "drop_count" + scratchMapName = "scratch" + scratchHeapMapName = "scratch_heap" + enabledMapName = "enabled" + approverGenMapName = "approver_gen" + approverModeMapName = "approver_mode" + approverPIDMapName = "approver_pid" + approverPortMapName = "approver_port" + approverFileEqMapName = "approver_file_eq" + approverFilePre0Name = "approver_file_pre_0" + approverFilePre1Name = "approver_file_pre_1" + approverFileHeapName = "approver_file_heap" + approverLPMHeapName = "approver_lpm_heap" + approverRejectMapName = "approver_reject" +) + +// Mirrors APPR_REQ_* and EVT_TYPE_MAX in c/common/approvers.h. Both sides index +// the mode array as generation*approverTypeMax+type, so the values must agree. +const ( + approverReqPID = 1 << 0 + approverReqFile = 1 << 1 + approverReqPort = 1 << 2 + approverTypeMax = 32 ) From 2184b50f249444ea43539aa065205dc939523c18 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian Date: Mon, 21 Sep 2026 16:05:36 +0200 Subject: [PATCH 3/5] feat(ebpf): Apply rule and CLI prefilters after maps load --- internal/bootstrap/bootstrap_linux.go | 4 +- internal/bootstrap/source_linux.go | 3 +- internal/ebpf/approver_integration_test.go | 140 +++++++++++++++++++++ internal/ebpf/approver_test.go | 125 ++++++++++++++++++ internal/ebpf/consumer.go | 1 + internal/ebpf/source.go | 52 ++++++-- internal/ebpf/source_integration_test.go | 4 +- internal/ebpf/source_test.go | 5 +- 8 files changed, 319 insertions(+), 15 deletions(-) create mode 100644 internal/ebpf/approver_integration_test.go create mode 100644 internal/ebpf/approver_test.go diff --git a/internal/bootstrap/bootstrap_linux.go b/internal/bootstrap/bootstrap_linux.go index 7a25fd788..5208dab0c 100644 --- a/internal/bootstrap/bootstrap_linux.go +++ b/internal/bootstrap/bootstrap_linux.go @@ -95,6 +95,7 @@ func NewApp(cfg *config.Config, options ...Option) (*App, error) { var engine *rules.Engine var rs *config.RulesCompileResult + var plan *filter.ApproverPlan if cfg.Filters != nil && cfg.Filters.Rules.Enabled && !cfg.ForwardMode && !cfg.IsCaptureSet() && !cfg.IsFilamentSet() { engine = rules.NewEngine(psnap, cfg) var err error @@ -102,6 +103,7 @@ func NewApp(cfg *config.Config, options ...Option) (*App, error) { if err != nil { return nil, err } + plan = engine.ApproverPlan() if rs != nil { log.Infof("rules compile summary: %s", rs) } @@ -111,7 +113,7 @@ func NewApp(cfg *config.Config, options ...Option) (*App, error) { return &App{ config: cfg, - evs: NewEventSourceControl(psnap, cfg, rs), + evs: NewEventSourceControl(psnap, cfg, rs, plan), engine: engine, psnap: psnap, signals: sigs, diff --git a/internal/bootstrap/source_linux.go b/internal/bootstrap/source_linux.go index c341c9b55..69765e6d9 100644 --- a/internal/bootstrap/source_linux.go +++ b/internal/bootstrap/source_linux.go @@ -39,8 +39,9 @@ func NewEventSourceControl( psnap ps.Snapshotter, cfg *config.Config, compiler *config.RulesCompileResult, + plan *filter.ApproverPlan, ) *EventSourceControl { - return &EventSourceControl{evs: libebpf.NewEventSource(psnap, cfg, compiler)} + return &EventSourceControl{evs: libebpf.NewEventSource(psnap, cfg, compiler, plan)} } func (s *EventSourceControl) Open(cfg *config.Config) error { diff --git a/internal/ebpf/approver_integration_test.go b/internal/ebpf/approver_integration_test.go new file mode 100644 index 000000000..e599c10c6 --- /dev/null +++ b/internal/ebpf/approver_integration_test.go @@ -0,0 +1,140 @@ +//go:build linux && ebpf_integration + +/* + * Copyright 2026 by Mostafa Moradian + * https://www.fibratus.io + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ebpf + +import ( + "os" + "path/filepath" + "testing" + "time" + + "github.com/rabbitstack/fibratus/pkg/event" + "github.com/rabbitstack/fibratus/pkg/event/params" + "github.com/rabbitstack/fibratus/pkg/filter" + "github.com/rabbitstack/fibratus/pkg/ps" + "github.com/stretchr/testify/require" +) + +// TestApproverDecisionsMatchLoadedPrograms exercises the compiled BPF logic +// rather than the Go model in ApproverPlan.Allows. The two are separate +// implementations of the same predicate, so the soundness property is only +// worth as much as this test. +func TestApproverDecisionsMatchLoadedPrograms(t *testing.T) { + dir := t.TempDir() + allowed := filepath.Join(dir, "allowed.txt") + require.NoError(t, os.WriteFile(allowed, []byte("x"), 0o600)) + + cfg := testConfig() + plan := filter.PlanFromFilter(mustCompile(t, + "evt.name = 'openat' and file.path startswith '"+dir+"'")) + + es := NewEventSource(ps.NewSnapshotter(), cfg, nil, plan).(*EventSource) + require.NoError(t, es.Open(cfg)) + t.Cleanup(func() { _ = es.Close() }) + + before := es.loader.approverRejects() + + // Inside the approved prefix, so the kernel must let this one through. + fd, err := os.Open(allowed) + require.NoError(t, err) + _ = fd.Close() + + // Outside it, so the kernel must reject these without reserving ringbuf space. + for range 20 { + if f, err := os.Open("/etc/hostname"); err == nil { + _ = f.Close() + } + } + + deadline := time.Now().Add(5 * time.Second) + var sawAllowed, sawRejectedPath bool + for time.Now().Before(deadline) && !sawAllowed { + select { + case evt := <-es.Events(): + if evt.Type != event.Openat { + continue + } + switch evt.GetParamAsString(params.FilePath) { + case allowed: + sawAllowed = true + case "/etc/hostname": + sawRejectedPath = true + } + case err := <-es.Errors(): + t.Fatalf("event source error: %v", err) + case <-time.After(50 * time.Millisecond): + } + } + + require.True(t, sawAllowed, "openat inside the approved prefix was dropped in the kernel") + require.False(t, sawRejectedPath, "openat outside the approved prefix reached userspace") + require.Greater(t, es.loader.approverRejects(), before, "approver reject counter did not advance") +} + +func TestApproverGenerationFlipAndFailedReload(t *testing.T) { + ldr, err := loadCollections() + if err != nil { + t.Fatalf("loading collections: %v", err) + } + t.Cleanup(func() { _ = ldr.Close() }) + + plan := filter.PlanFromFilter(mustCompile(t, "evt.name = 'openat' and file.path startswith '/tmp'")) + require.NoError(t, ldr.populateApprovers(plan)) + gen, err := ldr.approverGen() + require.NoError(t, err) + require.Equal(t, uint32(1), gen) + + require.NoError(t, ldr.populateApprovers(plan)) + gen, err = ldr.approverGen() + require.NoError(t, err) + require.Equal(t, uint32(0), gen) + + oversized := filter.BuildApproverPlan(manyPrefixFilters(t, 300)) + require.Error(t, ldr.populateApprovers(oversized)) + still, err := ldr.approverGen() + require.NoError(t, err) + require.Equal(t, gen, still) +} + +func mustCompile(t *testing.T, expr string) filter.Filter { + t.Helper() + f := filter.New(expr, testConfig()) + require.NoError(t, f.Compile()) + return f +} + +func manyPrefixFilters(t *testing.T, n int) []filter.Filter { + t.Helper() + out := make([]filter.Filter, 0, n) + for i := 0; i < n; i++ { + expr := "evt.name = 'openat' and file.path startswith '" + "/t" + itoa3(i) + "'" + out = append(out, mustCompile(t, expr)) + } + return out +} + +func itoa3(n int) string { + return string([]byte{ + byte('0' + (n/100)%10), + byte('0' + (n/10)%10), + byte('0' + n%10), + }) +} diff --git a/internal/ebpf/approver_test.go b/internal/ebpf/approver_test.go new file mode 100644 index 000000000..36ad5eb23 --- /dev/null +++ b/internal/ebpf/approver_test.go @@ -0,0 +1,125 @@ +//go:build linux + +/* + * Copyright 2026 by Mostafa Moradian + * https://www.fibratus.io + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ebpf + +import ( + "testing" + + "github.com/rabbitstack/fibratus/internal/ebpf/bpf" + "github.com/rabbitstack/fibratus/pkg/config" + "github.com/rabbitstack/fibratus/pkg/event" + "github.com/rabbitstack/fibratus/pkg/filter" + "github.com/rabbitstack/fibratus/pkg/ps" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSetFilterStoresBeforeOpen(t *testing.T) { + cfg := testConfig() + es := NewEventSource(ps.NewSnapshotter(), cfg, nil, nil).(*EventSource) + f := filter.New("evt.name = 'openat' and file.path startswith '/tmp'", cfg) + require.NoError(t, f.Compile()) + es.SetFilter(f) + require.NotNil(t, es.cliPlan) + pol := es.cliPlan.Policy(event.Openat) + require.False(t, pol.DefaultAllow) + assert.True(t, pol.RequireFilename) + assert.Nil(t, es.loader) +} + +func TestReloadApproversWithoutMapsIsNoop(t *testing.T) { + es := NewEventSource(ps.NewSnapshotter(), testConfig(), nil, nil).(*EventSource) + require.NoError(t, es.reloadApprovers()) +} + +func TestPolicyModeKeepsProcessState(t *testing.T) { + pol := filter.TypePolicy{RequireFilename: true, FilePrefix: []string{"/tmp"}} + assert.Equal(t, uint8(0), policyMode(pol, event.Execve)) + assert.Equal(t, uint8(0), policyMode(pol, event.Exit)) + assert.Equal(t, uint8(0), policyMode(pol, event.Clone)) + assert.Equal(t, uint8(approverReqFile), policyMode(pol, event.Openat)) +} + +func TestModeArrayMatchesGeneratedMap(t *testing.T) { + spec, err := bpf.LoadExecve() + require.NoError(t, err) + require.Equal(t, uint32(approverTypeMax*2), spec.Maps[approverModeMapName].MaxEntries, + "approverTypeMax must mirror EVT_TYPE_MAX in c/common/approvers.h") +} + +func BenchmarkApproverReduction(b *testing.B) { + cfg := &config.Config{ + EventSource: config.EventSourceConfig{EnableFileIOEvents: true}, + Filters: &config.Filters{}, + } + f := filter.New("evt.name = 'openat' and file.path startswith '/tmp'", cfg) + if err := f.Compile(); err != nil { + b.Fatal(err) + } + plan := filter.PlanFromFilter(f) + paths := []string{"/tmp/a", "/tmp/b", "/var/log/syslog", "/etc/passwd", "/usr/bin/ls"} + kept := 0 + b.ResetTimer() + for i := 0; i < b.N; i++ { + s := filter.Sample{Type: event.Openat, Filename: paths[i%len(paths)]} + if plan.Allows(s) { + kept++ + } + } + b.StopTimer() + if b.N > 0 { + b.ReportMetric(float64(b.N-kept)/float64(b.N), "drop_ratio") + } +} + +func TestApproverSoundnessTable(t *testing.T) { + cfg := testConfig() + cases := []struct { + expr string + keep filter.Sample + drop filter.Sample + }{ + { + expr: "evt.name = 'openat' and file.path startswith '/tmp'", + keep: filter.Sample{Type: event.Openat, Filename: "/tmp/x"}, + drop: filter.Sample{Type: event.Openat, Filename: "/etc/passwd"}, + }, + { + expr: "evt.name = 'connect' and net.dport in (80, 443)", + keep: filter.Sample{Type: event.Connect, Port: 443}, + drop: filter.Sample{Type: event.Connect, Port: 22}, + }, + { + expr: "evt.name = 'kill' and ps.pid = 9", + keep: filter.Sample{Type: event.Kill, PID: 9}, + drop: filter.Sample{Type: event.Kill, PID: 1}, + }, + } + for _, tt := range cases { + t.Run(tt.expr, func(t *testing.T) { + f := filter.New(tt.expr, cfg) + require.NoError(t, f.Compile()) + plan := filter.PlanFromFilter(f) + assert.True(t, plan.Allows(tt.keep), tt.expr) + assert.False(t, plan.Allows(tt.drop), tt.expr) + }) + } +} diff --git a/internal/ebpf/consumer.go b/internal/ebpf/consumer.go index ea5ea037b..36d466d6f 100644 --- a/internal/ebpf/consumer.go +++ b/internal/ebpf/consumer.go @@ -42,6 +42,7 @@ var ( lateSnapshots = expvar.NewInt("ebpf.startup.snapshot.late") enrichmentMiss = expvar.NewInt("ebpf.enrichment.miss") ringbufDrops = expvar.NewInt("ebpf.ringbuf.drops") + approverDrops = expvar.NewInt("ebpf.approver.drops") ) func applyProcessState(psnap ps.Snapshotter, evt *event.Event) { diff --git a/internal/ebpf/source.go b/internal/ebpf/source.go index e692659f1..c88a093ba 100644 --- a/internal/ebpf/source.go +++ b/internal/ebpf/source.go @@ -50,8 +50,11 @@ type EventSource struct { evts chan *event.Event errs chan error - filter filter.Filter - listeners []event.Listener + filter filter.Filter + rulesPlan *filter.ApproverPlan + cliPlan *filter.ApproverPlan + approverMu sync.Mutex + listeners []event.Listener loader *loader reader *ringReader @@ -67,9 +70,7 @@ type EventSource struct { } // NewEventSource constructs the Linux eBPF event source. -func NewEventSource(psnap ps.Snapshotter, cfg *config.Config, _ *config.RulesCompileResult) source.EventSource { - // Startup replay pushes queued events before the aggregator starts - // consuming, so the channel must be able to absorb a full pending queue. +func NewEventSource(psnap ps.Snapshotter, cfg *config.Config, _ *config.RulesCompileResult, plan *filter.ApproverPlan) source.EventSource { evts := make(chan *event.Event, defaultPendingCap) return &EventSource{ psnap: psnap, @@ -82,6 +83,7 @@ func NewEventSource(psnap ps.Snapshotter, cfg *config.Config, _ *config.RulesCom pendingCap: defaultPendingCap, stop: make(chan struct{}), done: make(chan struct{}), + rulesPlan: plan, } } @@ -111,8 +113,12 @@ func (e *EventSource) Open(cfg *config.Config) error { if err := ldr.setEnabledTypes(&e.config.EventSource); err != nil { _ = ldr.Close() + e.loader = nil return err } + if err := e.reloadApprovers(); err != nil { + log.Warnf("approver population failed, default-allow: %v", err) + } rd, err := newRingReader(ldr.eventsMap()) if err != nil { @@ -135,11 +141,21 @@ func (e *EventSource) Open(cfg *config.Config) error { time.Sleep(startupDrain) e.finishBaseline() - ringbufDrops.Add(int64(ldr.dropCount())) + e.sampleCounters() log.Infof("eBPF process source is live; %s", e.startupSummary()) return nil } +// sampleCounters mirrors the cumulative kernel-side counters into expvars. The +// maps hold running totals, so this reads them rather than accumulating. +func (e *EventSource) sampleCounters() { + if e.loader == nil { + return + } + ringbufDrops.Set(int64(e.loader.dropCount())) + approverDrops.Set(int64(e.loader.approverRejects())) +} + func (e *EventSource) Close() error { var err error e.once.Do(func() { @@ -149,6 +165,7 @@ func (e *EventSource) Close() error { _ = e.reader.Close() } if e.loader != nil { + e.sampleCounters() err = e.loader.Close() } if started { @@ -168,7 +185,24 @@ func (e *EventSource) Errors() <-chan error { return e.errs } func (e *EventSource) Events() <-chan *event.Event { return e.q.Events() } -func (e *EventSource) SetFilter(f filter.Filter) { e.filter = f } +func (e *EventSource) SetFilter(f filter.Filter) { + e.filter = f + e.approverMu.Lock() + e.cliPlan = filter.PlanFromFilter(f) + e.approverMu.Unlock() + if err := e.reloadApprovers(); err != nil { + log.Warnf("approver reload failed, keeping previous policy: %v", err) + } +} + +func (e *EventSource) reloadApprovers() error { + e.approverMu.Lock() + defer e.approverMu.Unlock() + if e.loader == nil { + return nil + } + return e.loader.populateApprovers(filter.Union(e.rulesPlan, e.cliPlan)) +} func (e *EventSource) RegisterEventListener(lis event.Listener) { e.listeners = append(e.listeners, lis) @@ -310,6 +344,6 @@ func (e *EventSource) dispatch(evt *event.Event) { } func (e *EventSource) startupSummary() string { - return fmt.Sprintf("pending_queued=%d pending_dropped=%d replay_applied=%d snapshot_upserts=%d", - pendingQueued.Value(), pendingDropped.Value(), replayApplied.Value(), snapshotUpserts.Value()) + return fmt.Sprintf("pending_queued=%d pending_dropped=%d replay_applied=%d snapshot_upserts=%d approver_drops=%d", + pendingQueued.Value(), pendingDropped.Value(), replayApplied.Value(), snapshotUpserts.Value(), approverDrops.Value()) } diff --git a/internal/ebpf/source_integration_test.go b/internal/ebpf/source_integration_test.go index f43c1feac..59e5b654b 100644 --- a/internal/ebpf/source_integration_test.go +++ b/internal/ebpf/source_integration_test.go @@ -34,7 +34,7 @@ import ( func TestLiveProcessSource(t *testing.T) { cfg := testConfig() - es := NewEventSource(ps.NewSnapshotter(), cfg, nil).(*EventSource) + es := NewEventSource(ps.NewSnapshotter(), cfg, nil, nil).(*EventSource) if err := es.Open(cfg); err != nil { t.Fatalf("opening process source: %v", err) } @@ -86,7 +86,7 @@ func execLookPath() string { func TestLiveSyscallTelemetry(t *testing.T) { cfg := testConfig() - es := NewEventSource(ps.NewSnapshotter(), cfg, nil).(*EventSource) + es := NewEventSource(ps.NewSnapshotter(), cfg, nil, nil).(*EventSource) if err := es.Open(cfg); err != nil { t.Fatalf("opening process source: %v", err) } diff --git a/internal/ebpf/source_test.go b/internal/ebpf/source_test.go index 7d01d2d1a..3503c79b6 100644 --- a/internal/ebpf/source_test.go +++ b/internal/ebpf/source_test.go @@ -36,12 +36,13 @@ func testConfig() *config.Config { cfg.EventSource.EnableNetEvents = true cfg.EventSource.EnableMemEvents = true cfg.EventSource.Init() + cfg.Filters = &config.Filters{} return cfg } func TestStartupReplayAndLateSnapshot(t *testing.T) { cfg := testConfig() - es := NewEventSource(ps.NewSnapshotter(), cfg, nil).(*EventSource) + es := NewEventSource(ps.NewSnapshotter(), cfg, nil, nil).(*EventSource) hot := sampleExecve() hot.PID = 42 @@ -91,7 +92,7 @@ func TestStartupReplayAndLateSnapshot(t *testing.T) { func TestPIDReuseKeepsDistinctUUIDs(t *testing.T) { cfg := testConfig() - es := NewEventSource(ps.NewSnapshotter(), cfg, nil).(*EventSource) + es := NewEventSource(ps.NewSnapshotter(), cfg, nil, nil).(*EventSource) es.live.Store(true) first := sampleExecve() From 8d352b2147fd2567a8b731a0f68a14ad31d6807e Mon Sep 17 00:00:00 2001 From: Mostafa Moradian Date: Tue, 22 Sep 2026 10:08:01 +0200 Subject: [PATCH 4/5] feat(ebpf): Approve file paths written as trailing-star patterns Let the matches operator narrow the in-kernel prefilter instead of forcing default-allow, by rewriting the patterns that have an exact kernel equivalent rather than matching globs in BPF. A pattern with no wildcard becomes an exact lookup, and one ending in a single star becomes an LPM prefix. Both rewrites are exact, not merely conservative, because a trailing star spans every remaining byte including a path separator, exactly as wildcard.matchCaseSensitive does. Runs of stars collapse first, so /tmp/** arrives here as /tmp/*. A star anywhere else, or any '?', leaves the event type default-allow. Matching globs in the kernel was the obvious approach and does not survive the verifier. A faithful port of matchCaseSensitive backtracks, so every byte comparison forks a path the verifier has to walk: at eight patterns it exceeded the 8192 jump-sequence limit, and cutting it to two patterns over 64 steps still burned the full 1M instruction budget across 29668 states. Directory-aware globbing would verify more cheaply but reject paths the operator accepts in userspace, which is the silent false negative this prefilter exists to avoid. imatches stays unsupported: folding in the kernel would have to agree with unicode.ToLower on every rune. --- internal/ebpf/approver_integration_test.go | 43 ++++++++----- internal/ebpf/bpf/ctl_bpfeb.o | Bin 48016 -> 48016 bytes internal/ebpf/bpf/ctl_bpfel.o | Bin 47632 -> 47632 bytes internal/ebpf/bpf/file_bpfeb.o | Bin 167576 -> 167576 bytes internal/ebpf/bpf/file_bpfel.o | Bin 166808 -> 166808 bytes internal/ebpf/bpf/mem_bpfeb.o | Bin 68248 -> 68248 bytes internal/ebpf/bpf/mem_bpfel.o | Bin 67960 -> 67960 bytes internal/ebpf/bpf/net_bpfeb.o | Bin 70208 -> 70208 bytes internal/ebpf/bpf/net_bpfel.o | Bin 69920 -> 69920 bytes internal/ebpf/c/common/approvers.h | 12 ++++ pkg/filter/approver.go | 71 +++++++++++++++++++++ pkg/filter/approver_fuzz_linux_test.go | 7 ++ pkg/filter/approver_linux_test.go | 57 +++++++++++++++++ 13 files changed, 175 insertions(+), 15 deletions(-) diff --git a/internal/ebpf/approver_integration_test.go b/internal/ebpf/approver_integration_test.go index e599c10c6..b8949d859 100644 --- a/internal/ebpf/approver_integration_test.go +++ b/internal/ebpf/approver_integration_test.go @@ -43,36 +43,45 @@ func TestApproverDecisionsMatchLoadedPrograms(t *testing.T) { require.NoError(t, os.WriteFile(allowed, []byte("x"), 0o600)) cfg := testConfig() + // Written as a matches pattern rather than startswith so the rewrite into + // the LPM trie is covered too. plan := filter.PlanFromFilter(mustCompile(t, - "evt.name = 'openat' and file.path startswith '"+dir+"'")) + "evt.name = 'openat' and file.path matches '"+dir+"/*'")) es := NewEventSource(ps.NewSnapshotter(), cfg, nil, plan).(*EventSource) require.NoError(t, es.Open(cfg)) t.Cleanup(func() { _ = es.Close() }) before := es.loader.approverRejects() - - // Inside the approved prefix, so the kernel must let this one through. - fd, err := os.Open(allowed) - require.NoError(t, err) - _ = fd.Close() - - // Outside it, so the kernel must reject these without reserving ringbuf space. - for range 20 { - if f, err := os.Open("/etc/hostname"); err == nil { + touch := func(path string) { + if f, err := os.Open(path); err == nil { _ = f.Close() } } - deadline := time.Now().Add(5 * time.Second) + // Keep generating attempts while draining. Correlating sys_enter_openat + // with its exit goes through a bounded LRU map, so on a loaded machine any + // single open can lose its scratch entry and arrive with no path at all. + // Retrying makes the assertion about the approver rather than about that. + attempts := time.NewTicker(100 * time.Millisecond) + defer attempts.Stop() + touch(allowed) + touch("/etc/hostname") + + deadline := time.Now().Add(30 * time.Second) var sawAllowed, sawRejectedPath bool + seen := make([]string, 0, 16) for time.Now().Before(deadline) && !sawAllowed { select { case evt := <-es.Events(): if evt.Type != event.Openat { continue } - switch evt.GetParamAsString(params.FilePath) { + path := evt.GetParamAsString(params.FilePath) + if len(seen) < cap(seen) { + seen = append(seen, path) + } + switch path { case allowed: sawAllowed = true case "/etc/hostname": @@ -80,12 +89,16 @@ func TestApproverDecisionsMatchLoadedPrograms(t *testing.T) { } case err := <-es.Errors(): t.Fatalf("event source error: %v", err) - case <-time.After(50 * time.Millisecond): + case <-attempts.C: + touch(allowed) + touch("/etc/hostname") } } - require.True(t, sawAllowed, "openat inside the approved prefix was dropped in the kernel") - require.False(t, sawRejectedPath, "openat outside the approved prefix reached userspace") + require.True(t, sawAllowed, + "openat matching the approved pattern never reached userspace; wanted %q, saw %q, rejects %d -> %d", + allowed, seen, before, es.loader.approverRejects()) + require.False(t, sawRejectedPath, "openat outside the approved pattern reached userspace") require.Greater(t, es.loader.approverRejects(), before, "approver reject counter did not advance") } diff --git a/internal/ebpf/bpf/ctl_bpfeb.o b/internal/ebpf/bpf/ctl_bpfeb.o index 769b9f2c6ff59b42f63a784d912f2d46b82eb699..0769585e811e3f8f658ee0e8720c87baf8f9f0df 100644 GIT binary patch delta 4220 zcmZ9OF^D5o7{@=~B(qu1^so~h|~w+BO)NG*vH*C@W!N;q*sYV;zJ!xddm+#z+B*E=cjH>B<uDxhA?kChz?DjV1Y;KCU2hXfLo+Wx}gicMXI{X+_U&)=05lX zayqXt4=pY-k1W2zJQga=y^(R~GB~ z2KyFKB7t8eHH&$bqv3n$(n^-woVgylHqDeC-=JmPo6oumIAskvUi1ph#4 z!HKy@#GR3Pq6b_@^#Qq0Nd3-FxRXYM;iB-)E~&rxC)sI$-y*fr>rcV&k@_b=wA%)M zMr!Rbcfj{aJ>~kI;Xg@jIHA2Lkym-6HK~93fW09aG(Wii;Z+sMkq+cG;Yyc;jU4F{ zFyu(%xe|~ggL4y*Bh$lr$dTy_8#yv~3_ece$c(T6a%3i8$dQ?XAxGxIVoo|U14E9? z+~OkF7Z$S|nU%0PpE7GKfE->53^}~C#r#uyIg9yK@c0n@=OYO@ypqMb-T*@m??gD3 z!)xOPlmAok!a(EZQu^isz)`F$5k;7XH#|Lgu zhaA})`XNU)07H%}5^*6%wi?x+%aLuP0diz9v5_M?l==?j$ex2C$F(sSa$K8$A;-R9 z$gv+KV#%>TM}wB*`(HnPEpp=^C3nr-2WesB#z6pv8wZ%vxZyWYha3JW7;g9&+qmI( zrOxMx8-7o2B;kfX1j7w~1cnopg-eqk}Y;a>`y^U0rM0o?Fc zV7TG0EoL|Tjm7-#=Xn&{jeOc-UFV00>Tn|;2*+;ZtGEF-@(qjGjr@tl>_)yV%;!c| zzJog4$PX=MH}WGe+{m8`$8O{&TMK5w#*I7@lH+*81?q4kzd=9TD5St}qku$QxKYSO z_2+IBs%U^41x#$*D0HQ6+$i+HaO3(J7;ao2g5k!YVYqP^C1Sa8I7LI`hVzNIak!Sd zX6{4GY23Jhxy(n^4VjCK8$lrb=Kn^3F%xhjXh_|-5uC>7i5o#13*bi31H+A=4~827 zaxiWLnA^A!oMS!Q2*wt(8^KgKb|bjJ0=N;(!Ehs3Sj=t&ON;s44_09O-v~Aqb3IIf z;YOGij@<~0xB)l9z+!eIELqHMgbiWB6`r6DH^QF9>_*rJ!;SDvICdi(Z7rAx8#h8E z6dyQ49d3k6^uvvC4Tc*b5^>?i5pTqQEuOn^R73;ZIKsrnjiXbk8#j(RV7PI!3x*pv zdtkUxG7L9LQ6l{QnUAW{IU4YhRYC%(cgaccZ(h2Tddze1*W}FjH!dwL=AWpvvRK!V zKe{7_FA?H%xNTcB~IS+Y*G7=$N21* z6+M|A43k!JU<_I*f-z{NBpmBlsbT>ptzfd0W}dXtk-C|*(lZ-SbXEGoX41+CtOw;} zDib30m6Z#xn~Z7e*?=4QsyBp92=z7?A=EiEJB0e!gm7!{6W)X- z-;16BZ$fh`gyse6Ius6}IkT8UXl{kjT%wK;np+_>H&Ty7Xb~C^LMvx6htS#zp;a{- ca3f!>hOh~t)dnMk)>a6uu?gY7JKt9S2ixrH#Q*>R delta 4220 zcmZ9PKZqlB6vyAqB(quX){B{NhFxZoEB2UK4ona>5lo0CMT+xo%YYU+I53D{z`}@N zmaEc;@lUbE6@hDlS_ID`gVoGx3oe8cZ;&-s4HIG6j(LhYzatZVN1O%vACdKgTE7B+ zN7hfAn1e)|IayOR;3ldM$azNAjPGzSjRwsH;k|vb=KM(Z>fpD?`c17r1K%a%mfTMGE*?*$jl7pq%(6c z-3Z4U zZc&FE*&O;IM>YUMjw}*!AV;@1iIYd3r(B-`-?m#D)He~W&&kxzl)MjnYca3i0K z>Mz{LSI_`A@|ak=k?%@fyOHmM;l|B#FxIixWIb25sVFHH-f2f>_#xd0=N+@z;Gj28q974D}(vn57uD(-3Yb@b3IIf z;YOGij@<|gH~}}pz+iSGEE>#igmq!U5w=i=8)462b|dVA;YN5a9J>*Yb{0&8wHqN4 ziZ`624mZLT`r$^n0mF?Di8yfMgfGOu7BAd5DWCyvoM2+@#>tt~wHqfLFx*GbZLq2% zfzy`e$$35<+z>J^FE1xhEP5Lsn-7a|qSB!MsOx0Y(Vb6&N8@ z*I@ZZC)D*pqak=zjg diff --git a/internal/ebpf/bpf/ctl_bpfel.o b/internal/ebpf/bpf/ctl_bpfel.o index 23b8cbee96b4dfdb371c8b252da95e80e1f68c69..c61f26b2b36651868ed7027f81642dce6b7c49a1 100644 GIT binary patch delta 4221 zcmZA4F^HRW7{~F)H`iR!=6b0oHMG>mf|5$X*TqIqiP|B9){Fs{I5mjS;2=??35UbG zlm_jPp+mqW=n}XkgJ^~hH*^TJLlB2U6f!tOIPe`De4hM&zx27@aBn~VH+kRtKlgr* zbZ{IEj-$!BTfHQbqe$fZmTbP3a9!6<4-}bjeqWuvA4v|rr;Z*(QaTmR|E#`H%}514 zQeS*KBQbnRkJ)l0HP~+0vu|}Q?CCLgEs_>|Lyy@wk~aLY9`n^mI?iX+UHDTyo@-?! zaW1O|&S%sknD>`47VM4r&oeTE?O5n!Qj zhKZfY>i!G;j1;kONsnjmXQbqORb6&2sAJfsXJ1wLLp|n(8EH9htK0A$J!Z!l>Cip> zM?n|*T)+#4@LTpfe;COa4!0AT!0Tt^Q6zKtfgZDSeWu_a^|-r;WC_poc=kyoE4cSW z|FQjhB*pD861oiM^_c%t9~$^QJ#On0+JJBBaqI6$n)&eluhe@heTLv4?EJBMC!GI7 zolEtZ3Vu;mx{&`bk_0aZKDhGPZe(#(is60ScnmX+I?Om4Fym-FAKuS6Ixyqt!i*z< z?SAVx23TMmW0-MFV8$_Zwm4=m12B#;%s9pu!ga<(>7XKO=V3KL)(MQ3ZH46}_2ylJC~ z1-4Ohwl?a{))E#^7T87yW*c3YZSVLy;Q|G(P8p?Ke;Y34_5Vr|N#A^0KQ!Oeh3r;zaPZ|XQBQX|eKU-TJDD<|Nx^T9gE@AF8 zg}G6=96z3-TFzWeQ~H`8 delta 4221 zcmZA4F^HRW7{~GF-nY#qZSF4hjv88OW5JS&U|j48Dp5ORs5N6ihqq8Lh|thMqC*pI z%2FECAw!3NOHhZvIb;yc;E=%~&<;Tyf*@p!P%wjo&y)Y}mp<1U?(OIQChvRy=iYD0 zb)QDvr_u1-r>#4Y%p;NWr)2ZBfGfIo=5s|H&L62$jY!h)Lv_@QB!4=b|5<(EAeJIL zS6|G>Qi4zGG48-I+6swp~qA z$GM>HI-gbdVcuT`SgOz|fctH<-%YNtmNCt4YoyZVgKO=)krtl*@rhe3C3jSV?dp||8fX8~=9Y(T*TTk>K z+oMQw+hHVh0nX?#GmfMTzo*CT-y*5PxAb^w5=ku+-v6a~|95?c;P34GRJ{|<|D{ep z(Pt|7MOo@XW)?{YF9<%q^4VTwaTIgmecX5nW*ilmaa3W(k-QMz&o~+|<7mQ+qXXOh z)^T*Pz&Hjl;~2t>W8`dcjA6zxb+$NW&KAc4=KW=f1;&xy4?AKUIcJL_?`&}tV8&5$ zwm8Z#GZH!^IF@<@<8O%0TFxyC94ijM;Ihbwa z;Y}NdSYR6!m~GTyw$X&yM*HP(L$=X@*+%D;aGq^+gP*lA#0${I(YyPw4JSu4$L-s&elfX+1ePw zyuXaFz&55Z+n7098*^uCV*#^`m9w>xz7{6LHgfQ$jRF?fM$y^YC^=gjW!R=?Ulo{b zG@PxCCd@Y4G~4KM0c{LmwlRXk?L@{f+nB>_V+pg370fo|)i9Aw8wD(|jS|c@sxaF~ zV75_zEnJXoG+?&TD24NEqZ!=Ve5mT-1^kdTfIm#@$3p$PWAdD*@B=-c>gqG$oK-KJ z?feS<7~4|5sb+=?Cleg2-ca_FMfA73Ro`@ZWkq-PdQpd0SnD*O^VX zBzf-rbvU2Vzm@*nlD7GberUd>3#s|m@$nbGL@nLv=*=)H?tBb$r&DL!>CD-7x`4UU z70ivw^>BS|GzZ&8*Z&{nvA~^{oNcFNm^-by3)n?!Fn8L3u~F%$AL}2BAKS+DFNP8P zAS1_jzq%6J5R!LJ4xtWn2u)`jLfhGf(1kgKKFlEuU=CpfZ-y|&0*5ejwjnHF4q@dk zU>A{h!v;8nJj@}K)P4vFY(sc>|LgUWQ2yZL5GpW-P;<5+B+fR32FxL}VGf}Ka|k_n qGlV`CIE0b24PgRv2s3v9yT}~o5LPgUkh^hm2xZuYaQWz;>;D6YJlwnh diff --git a/internal/ebpf/bpf/file_bpfeb.o b/internal/ebpf/bpf/file_bpfeb.o index 77478a41aefc426cfa05720e249cc9cd43b86524..46747d3c1d3006e7f1efa3450364162d558e9a86 100644 GIT binary patch delta 7595 zcmeI0ziX307{|YN7xE@=t=fj<)e3K_lY(d_lR*SsbhBc?ZpJNxNCr`dLNXK@aLEvO z6ZORof^n-*sDomLiUm7l@J9r}Qbim@GF0qP(C6|#39tSI3Ec1wpL_0o?!I^Lm*?KA z`*z*8%PZnkLsYzML!{4EZ9rsz=sZ0iA!||M9P>BG2NF;h0=5#6j}(xY3s}8^tau)! zxunx1D*PI!NmTz$lWcOD8K~S8kbK5`6YBIK;udoQa@w=*iS)JOF>3B|a|bd*vrFzU ze}T-!ffPc#mzdtsYOG&S`3d3!A)Y3tXAt)mX_(S=on|Izj?F?9_Ykwl9`7U0hvGDi zRDt;h)V%J0C&W5lVZIBsFiy;?5qk(#*8P__{uD=4P0zbIXi&9d#LFS}&fllysFSo5 zFGp+>s%{bUa>OU0nl!FMeYCs*?+-C3&hiKGToBirx#qp5VM-gcnNE>k%Rshu+A{MQ z$PO)s!}8*@kZ)=BPL<;Y$WJsaXZb&FG5e5TX}O(E=68_ab^k8&7E1C*1USgL>~Y9$ z0-z73r_0VlZd2Ut^DW37((JNsdjWEn25^sZ|30%$`#DsE1h{h??{l7c_cBzA6uX6f z12JuwTMV&|mjfP~g4&=BcB{-Mpw>0lna@G3d0Ahi54ZI^*SVR#vo;BLI{{k_h;8q- zFWgB9+JH3m)%!U10y47t*cX4I#;rp}r=%V*`G_N>(spN(gYXZiov)Y%cJvsd1Tljdw}JZn6w?|24x rQbS#5f4?{Xv;BKzb2c_-<54&puWpH}rp}r=YwGOi)Y-+KVq)np4hpzB delta 7595 zcmeI0ziX307{|YNCwY^%t+q{*w^n#lopjMorh^E&*g>#j!3=^CGGq|RAey0&3_=So z8H6`cU(99%hX{doP|ToM(4m7rA_#^Gj?zVRDCl!}pM+Qcf&^}OhtECFdw1Wv_u+f@ zR(-qb+vS!xSra)gT@$G@*KI&70FhOCK0_8F#EZ<|A&U}FO95MP$g%?BnSj-6$eia< zHy3p`@pXQUyNOr+?IzLSZkC~D=77W|^G&GPL&R<78pNJw-505A(I_?Va&rfAoMxB! z&HN2=CI%!C;{C+*j#gv+ggP}vJR9P9VtNK~Z;gg2E$MESgXZW8)cJ8@7TMzi#Mw}s zrjg7u-+;>K{9=f8e4Y6&RCa=xS0nle>Wa>-$B3ID_Rc+^<;at? zBriv_3zfHsc{yU!P(>Qop&Tu5z>^^c#pgq;^A`iwn_2hX&@iP2ZKhM;v<1kgI<3rn z8nQ*p;jp~e3S^UJ?^HORhuoxTInDpL&Fn+AX}O&)^9RURI)9gW2PL_+4>-uW>GM|OI=cRp-I$YQD+~Q{X&gvxG?F4MmSHJDu z_JunwzR(7wC|B>}*b9j6#$#XniI|%0)wHQuQ?p#dLtV4Z6LG;ZHEU`%@MZQN?ruG)fQh(&6=9!`>*lY;C?&QXXDFn#R+pZHZ^N%R{!G} s{F55$n*H_B+-Lj$mCf1MoQ+4}Y`n1}t{R^;K5Kk-bbNO0hnTAW1+Tf0vH$=8 diff --git a/internal/ebpf/bpf/file_bpfel.o b/internal/ebpf/bpf/file_bpfel.o index 6d3b223d858710c41ced1d3a7e82ed1c5bc8d599..610f1b10eab08db6c823ffa7fbf5a783e664400f 100644 GIT binary patch delta 7603 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 diff --git a/internal/ebpf/bpf/mem_bpfel.o b/internal/ebpf/bpf/mem_bpfel.o index db032814f4af231089eedf0b9c55148ca480c9c5..dae3f656bc7b94772dd07e3d1b5fa7c00e419374 100644 GIT binary patch delta 2829 zcmeIzv1=1?6bJBcf4}3Gq)ijGShY$o76%oF;&g(DP6{H5F5OHwQHP8U!UYt~Bxf%} z1qVTgAmmJS5yTRqLxv6=96A(nP;e-cp~DGM{Qhz;c;qkWaKjCs_uf7D-MhyxUUK3k zr_*kaHNvRvUJ4ZE$AHrYc*@5#6+Cg1RxcH<=p_Gz)^8LRrV_tk+%&>ctOQMF1yTl8Xv`TIpFAdjjs4IZ7M4CquIqX3VjJbvEg}zSp1wWcnX+K+FFKbMy`KfT||3iGR}04n3Rr#5jud_f2kQX0V=%|Y) z9(8FQkKa0Am-!iuZSi6jI5nry5nrdxzlQGy3(J;5U&2qLu&po)a>+jk9GB<2D^X*VwK}34;4J|ES=p}2*=zJ-()`5QRs=E zMD<@eVzEcNnJ#C1GCsy92ByDp#`Cd%(wSX)A@8|qLO?Nfj)##o* L)c2~}{d4sn1FnAG diff --git a/internal/ebpf/bpf/net_bpfeb.o b/internal/ebpf/bpf/net_bpfeb.o index f4ccf10ccf7f3dea24b37193e0ec57d438ac052c..e8851dbd5cd3cfde74b9c502adbde5cdf3f21402 100644 GIT binary patch delta 2961 zcmeH|&r4KM6vvPE4$d33G?jS|g?FbGY2-qP%Akcolsk^Pa@LdS(ZlBM~TOt|{l5&oX;Q>N~*eBnEuWJ7ZkM+!fbfpDduD)Ql0L0ucs#Umz6wviaEWF7}!A@N2K$pZKRi3v&6P&6#xk;sQPr`0XJ zOT+HrT^jZe?~+Cf$+sjsnuyY^$X7^SZDwug$>%4CTtfbvnvp!>a*S zFOVEdGWUb;lbqtOb-e0Dy%IqN49KloH$<_NcgcS-!>VS7D>t6E8H>-qqEk#b@uLDYn{ssa+b z4a`{-yd<&5xo`OkiG3c6kG8A6llaSD;E$o+GTN-JC7Iv`{8f`jTmpCBCRyZ;{SCXo z%&*JGM5?=yZzF$1a*bcFzYl&&a+R3{E>EQTHOb|0>w`L7;$y0Itn#HQao?)baB_z# z_QIAqzg`fJU!l92IueQ5-nqpjtLiQoRYeD$fvUpp0aX({$f0UuVA!ZSxL{Om967v8 zBLSK~;}X1vNc1Z&mcTpe(%3xz3y^z~R(lEJa6=CT~C PYW@WOLseJSA7B3muHL(n delta 2961 zcmeH{ziU%b6vt2Q4b4kaHMSw|q3~{WuoWE&;xFh>K{SKVih~Xg5u#>L=+-)=;$U&A zJcSMp0V^%&khY2isZBs=1;q@49YnIVgF|t#gM;V3`@PTC{sj&lGJNj$y!-As?|#yl zPBx~K^$YdtK$a*$L><@p_mae5H?sq-k{D3TTodM+k1%^X>d$~blPLO}55~BYxftU- z^YA|w#bBkb66IjMuFl=j#gisX9Vao;!CV8MB{3$5WF35q#JD8tX&9C-NR)$%bLz6* zrDt>dE98#Gv0V&@7i9S;Gaprd|B!><^Xf*$;nfmW zPmrvnm@D9$B**x*E}BnU9*^aG1Q*Rm`K-zHhpYvo3#vNHAJT2(sRtxp>0LL$k4e1d zVYp~6Jwu|-XXm4vv%Vv-$fxoOJGdXbNut5S_J$32_L2CY>r3F1R28d9q628Fvqa)k z5Az5L9+7Bq?pyvy;wz8EN86p>NUZS-{3+C1Mw^*^B--47ziRS`Ti~H9BqzCJf6Xp1 z^XKw0k<1YC4di!8KI6~pZ-MWVoML8y!--^`l6(@ZzgCB8d`#7kRlZa;?pqBSPVt3r z1-)kxT^ib918R$FhXx4W=3x=xp&O4e5ocG1@ z;P!i?s(THqP}MpSs;h5jC6?>kI|7EP?s$xKj#)&iVit~7b=K7XQx(IBR9%b;WI57w8mfAPDyZq9d8?ww1)=ad=UNZVNBN-1jjA)tMpchX!>6FCHvxvK9-50(okDI^ zUEIN|V5{ne;YigjuvL}+x5EQiRS!B~sH!YORfV>#s@92!(WX^XmCSw-SHMq Q)$p$&^B=0Z^7-ERzp10E+W-In diff --git a/internal/ebpf/bpf/net_bpfel.o b/internal/ebpf/bpf/net_bpfel.o index 217e34e79e8dc89e5fbcda368982b6c582c0c5c3..9b8be175634ab5f8b59916eafe83fe336e1c3c16 100644 GIT binary patch delta 2964 zcmeIzy=zlZ7{~F)b3>Ba*v3|BQ0a{hwPJ^YC>0zkE^dkrIyl^dFC8j$>>#9~l;9M( zwPX+}^`!+tqjnH{iy&G-A%j#0kq#;yIut1y!NK3T_xIF8{sM;%9X`)Fx#aeoZ#y}a zn4C&fzTGbbMr57HsieqV{Is1mlBNr=kM*qME;!e)zmI;8{hdQb`W>%_4?FIFk2*Hn zhQhNIe_b>M~^?MoL`lNr@!KjZD(}VRPL`#f!h}S=hT}q}m?)Hs;A<_`TvE!&8j6)C=_NRsH{po~odZ2a0*-g5G43@oNbiH2`iu-a zZh=SW!&u)Kcv5tnhf9u|gK++VUl{VF%IP#dl^OPA&T%VTbDV@f(J$@(3!W@GPQrEi z3)VMW#_wr!{PI8S{!ve|bfQUQN6WY;IcKm7&O6SGhZ7I|fwCt7r+e_R6g)_ufs-?y zj5K)Ev0%OA*zTX9qmz6Uc0BS6?~E*PddWVuhLfeQ!mXc-)ahxs ze1m)GWvn-S#buHBJhWBKLt8!fENWG6y|ya6DB5b;v29f= z&{p$Yx3;ZzJ4UPDpGB>nhKt z+v;P-X!XwXs8y{*Th&Um)hutlI_KE7+U?l3+E269t`||OBb;ihMOs@e(b{U6)>a=k zc#hUq7in#^POr8qTjL9+t)^*hHO=d+t!8O$RijXA6xwRQ{pvw_wN>o}gQ(S!e;cBf zi?p^{rnS{cnypS$qgHF2YO4!0Tb-{)t!DG_%WJEtm-p6M6TnTiyBo G_o2V1CBGv8 delta 2964 zcmeIzziU%b7{>88=Z5@f(>AuHhE{r`LyhQA5T!zgh)V{+qJteeq!4Qcg^bx!5lV52 zTrC+yLPc9pG_@HDwwi)y1q&IZb`Z&8>EIv^8o|N$-21%kA%B5GhYp|joLqWy&bKYk z`^)qG%C{GVQAOk>q(QdH-NaQPOZ5J7u_!J!V)P zNjXy$+m~@>D)#vsii%h~6(kDe6qVs~Y?W73vAkb)ifv6Rs`Yq&%=19T*{Rr<`6)jz zm8Udec}lF$`_v6>vOIy4Nis>r7=Dk;&DV#7Cy@k_bSR6 z?quiT6t5o|wP@CGoLw~BKI&{O*@cuvHB1-yQ;~}nZ5Zxi*9`~Q+wi*HKW@>k;Q+e{ zf93U#G=EQry_f%~_fJ?9h5ccoW1Sg`V#eSEJ8n3VapqpylUa+>n4ad31=(5n8at4; zDBt2~!^G=F!+QTB?4D%V>07o7i;5bU-qufj#wQEkWp`B-HQ@zzXN50w%zL?4?BI%` zc#DVOAG{u}@nwV)ZM^?2A2ED}UGQ)48TWe+O!J`UBcCyRhwZPk2fg(V?9eAZbNDkm zysfCz;zhWtonN4#Xrsk-_)sF-#X*G^@ZQW|ZFt@t1=C(SHskE9ltXq{R^tx^}hjnRn+OTd_qL5ZgSeI5MlD$?d z*q{fx)fL0s>XX-Qt5S)yDwRm9QQUfQ%&=}XVOY1Cgwg8I8@JUwrqb#xEUgw{X|)7P zt1B(ufTh)4SXynud#%!dcfq995G<{RaGj;qC@if?6k>@&T1{iWI1BH!D!uT)Z8g8Y z!EJdKmR3u!v|5JI>RiojwT`K@+JMpOR?TfS8uwmaS`Ds0KWLTcpjA|I(5m~->c4FD J_~xGr{{WKMuWSGS diff --git a/internal/ebpf/c/common/approvers.h b/internal/ebpf/c/common/approvers.h index 0aa935591..c9496b3f8 100644 --- a/internal/ebpf/c/common/approvers.h +++ b/internal/ebpf/c/common/approvers.h @@ -15,6 +15,13 @@ #define APPR_GENS 2 #define APPR_MODE_MAX (EVT_TYPE_MAX * APPR_GENS) +/* There is no in-kernel glob matcher. A backtracking matcher forks a verifier + * path at every byte comparison, and even two patterns over 64 steps exhausts + * the 1M instruction budget. Userspace instead rewrites the patterns it can + * prove equivalent to a prefix into the LPM trie below, and leaves the rest + * default-allow. + */ + struct approver_pid_key { u32 gen; u32 type; @@ -39,6 +46,7 @@ struct approver_lpm_key { u8 path[EVT_FILENAME_LEN]; }; + struct { __uint(type, BPF_MAP_TYPE_ARRAY); __uint(max_entries, 1); @@ -111,6 +119,7 @@ struct { __type(value, u64); } approver_reject SEC(".maps"); + static __always_inline void account_approver_reject(void) { u32 key = 0; @@ -214,6 +223,9 @@ static __always_inline int event_approved(u32 type, u16 port, u32 truncated) if (*mode & APPR_REQ_PID) { pkey.gen = gen; pkey.type = type; + /* The init-namespace tgid, which is also what fill_current_ids puts on + * the event, so a ps.pid predicate compares like with like. + */ pkey.pid = bpf_get_current_pid_tgid() >> 32; if (!bpf_map_lookup_elem(&approver_pid, &pkey)) return 0; diff --git a/pkg/filter/approver.go b/pkg/filter/approver.go index 12b4bb42e..453bdb94e 100644 --- a/pkg/filter/approver.go +++ b/pkg/filter/approver.go @@ -371,7 +371,28 @@ func extractFilenames(ex *Extraction, expr *ql.BinaryExpr) { } ex.FilePrefix = append(ex.FilePrefix, name) } + case ql.Matches: + names, ok := rhsStrings(expr.RHS) + if !ok { + ex.Unsupported = true + return + } + for _, name := range names { + literal, prefix, ok := globAsPrefix(name) + if !ok { + ex.Unsupported = true + return + } + switch { + case literal != "": + ex.FileExact = append(ex.FileExact, literal) + case prefix != "": + ex.FilePrefix = append(ex.FilePrefix, prefix) + } + } default: + // imatches stays out: case folding the path in the kernel would have to + // agree with unicode.ToLower on every rune userspace folds. ex.Unsupported = true } } @@ -487,6 +508,56 @@ func clonePlan(p *ApproverPlan) *ApproverPlan { return out } +// globAsPrefix rewrites a matches pattern into the exact or prefix form the +// kernel can already evaluate. There is no in-kernel glob matcher because a +// backtracking one is not verifiable, so only patterns provably equivalent to +// one of those two forms are accepted: +// +// /etc/passwd -> exact, no wildcard at all +// /tmp/* -> prefix, since '*' spans every remaining byte including '/' +// * -> vacuous, matches everything and constrains nothing +// +// A '*' anywhere but the end, or any '?', reports false and leaves the event +// type default-allow. Callers must pass the pattern through collapseStars so +// /tmp/** reaches here as /tmp/*. +func globAsPrefix(pattern string) (literal, prefix string, ok bool) { + pattern = collapseStars(pattern) + if strings.ContainsRune(pattern, '?') { + return "", "", false + } + switch strings.Count(pattern, "*") { + case 0: + return pattern, "", true + case 1: + if !strings.HasSuffix(pattern, "*") { + return "", "", false + } + return "", strings.TrimSuffix(pattern, "*"), true + default: + return "", "", false + } +} + +// collapseStars rewrites runs of '*' as a single '*'. The two are equivalent to +// matchCaseSensitive, which only ever remembers the most recent star position. +func collapseStars(pattern string) string { + if !strings.Contains(pattern, "**") { + return pattern + } + var b strings.Builder + b.Grow(len(pattern)) + var prevStar bool + for i := range len(pattern) { + c := pattern[i] + if c == '*' && prevStar { + continue + } + prevStar = c == '*' + b.WriteByte(c) + } + return b.String() +} + func matchFilename(pol TypePolicy, path string) bool { if slices.Contains(pol.FileExact, path) { return true diff --git a/pkg/filter/approver_fuzz_linux_test.go b/pkg/filter/approver_fuzz_linux_test.go index 910bd6b5a..6e64728c0 100644 --- a/pkg/filter/approver_fuzz_linux_test.go +++ b/pkg/filter/approver_fuzz_linux_test.go @@ -37,6 +37,13 @@ var fuzzExprs = []string{ "evt.name = 'openat' and file.path in ('/tmp/a', '/tmp/b') and ps.pid = 42", "evt.name in ('openat', 'connect') and ps.pid in (1, 42)", "evt.category = 'file' and file.path startswith '/var'", + "evt.name = 'openat' and file.path matches '/tmp/*'", + "evt.name = 'openat' and file.path matches ('/tmp/*', '/var/tmp/**')", + "evt.name = 'openat' and file.path matches '/etc/passwd'", + "evt.name = 'openat' and file.path matches '/tmp/*/evil'", + "evt.name = 'openat' and file.path matches '*.so'", + "evt.name = 'openat' and file.path matches '*'", + "evt.name = 'openat' and file.path imatches '/TMP/*'", "evt.name = 'connect' and net.dport in (80, 443)", "evt.name = 'connect' and net.dport = 443 and ps.pid = 42", "evt.name = 'kill' and ps.pid = 42", diff --git a/pkg/filter/approver_linux_test.go b/pkg/filter/approver_linux_test.go index 8d60a95ea..0eaf07089 100644 --- a/pkg/filter/approver_linux_test.go +++ b/pkg/filter/approver_linux_test.go @@ -23,6 +23,7 @@ import ( "github.com/rabbitstack/fibratus/pkg/config" "github.com/rabbitstack/fibratus/pkg/event" + "github.com/rabbitstack/fibratus/pkg/util/wildcard" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -100,6 +101,62 @@ func TestProcessNameIsNotExtractable(t *testing.T) { assert.True(t, mixed.Policy(event.Openat).DefaultAllow) } +func TestExtractMatchesTrailingStar(t *testing.T) { + f := compileApprover(t, "evt.name = 'openat' and file.path matches ('/tmp/*', '/var/tmp/*')") + ex := f.(ApproverProvider).ApproverExtraction() + require.False(t, ex.Unsupported) + assert.Equal(t, []string{"/tmp/", "/var/tmp/"}, ex.FilePrefix) + + plan := PlanFromFilter(f) + assert.True(t, plan.Allows(Sample{Type: event.Openat, Filename: "/tmp/dropper"})) + assert.True(t, plan.Allows(Sample{Type: event.Openat, Filename: "/tmp/a/b/c"})) + assert.True(t, plan.Allows(Sample{Type: event.Openat, Filename: "/var/tmp/x"})) + assert.False(t, plan.Allows(Sample{Type: event.Openat, Filename: "/etc/passwd"})) +} + +// A trailing '*' spans every remaining byte, separators included, so rewriting +// it to a prefix is exact rather than merely conservative. +func TestTrailingStarRewriteMatchesOperator(t *testing.T) { + paths := []string{"/tmp/x", "/tmp/a/b/c", "/tmp/", "/tmpfoo", "/etc/passwd", ""} + for _, pattern := range []string{"/tmp/*", "/tmp/**", "/etc/passwd", "*"} { + literal, prefix, ok := globAsPrefix(pattern) + require.True(t, ok, pattern) + pol := TypePolicy{RequireFilename: true} + switch { + case literal != "": + pol.FileExact = []string{literal} + case prefix != "": + pol.FilePrefix = []string{prefix} + default: + continue // '*' constrains nothing + } + for _, path := range paths { + assert.Equal(t, wildcard.Match(pattern, path, true), matchFilename(pol, path), + "pattern=%q path=%q", pattern, path) + } + } +} + +// Patterns that are not reducible to a prefix have no kernel equivalent, so +// they must widen to default-allow rather than be approximated. +func TestNonPrefixGlobsAreDefaultAllow(t *testing.T) { + for _, expr := range []string{ + "evt.name = 'openat' and file.path matches '/tmp/*/evil'", + "evt.name = 'openat' and file.path matches '*.so'", + "evt.name = 'openat' and file.path matches '/tmp/?vil'", + "evt.name = 'openat' and file.path matches ('/tmp/*', '*.so')", + "evt.name = 'openat' and file.path imatches '/TMP/*'", + } { + plan := PlanFromFilter(compileApprover(t, expr)) + assert.True(t, plan.Policy(event.Openat).DefaultAllow, expr) + } +} + +func TestVacuousStarDoesNotConstrain(t *testing.T) { + plan := PlanFromFilter(compileApprover(t, "evt.name = 'openat' and file.path matches '*'")) + assert.True(t, plan.Policy(event.Openat).DefaultAllow) +} + func TestBuildPlanIntersectsRequiredFields(t *testing.T) { pid := compileApprover(t, "evt.name = 'openat' and ps.pid = 7") path := compileApprover(t, "evt.name = 'openat' and file.path startswith '/tmp'") From edc5c1271c30912a94bd343ef4b0e2508306ad64 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian Date: Tue, 22 Sep 2026 11:56:42 +0200 Subject: [PATCH 5/5] test(ebpf): Cover path lists and separate capture from approval Pin that a list of literal paths resolves entirely in the kernel's exact-match hash, since nothing about it needs the wildcard machinery. Run the privileged prefilter test twice, once with no approver and once with one. The first pass establishes that the capture path reports the open at all, so a failure in the second pass is about the prefilter and not about an enter/exit correlation that lost its scratch entry. --- internal/ebpf/approver_integration_test.go | 98 +++++++++++++++------- pkg/filter/approver_fuzz_linux_test.go | 1 - pkg/filter/approver_linux_test.go | 35 +++++--- 3 files changed, 89 insertions(+), 45 deletions(-) diff --git a/internal/ebpf/approver_integration_test.go b/internal/ebpf/approver_integration_test.go index b8949d859..a29af5e27 100644 --- a/internal/ebpf/approver_integration_test.go +++ b/internal/ebpf/approver_integration_test.go @@ -21,7 +21,9 @@ package ebpf import ( + "fmt" "os" + "os/exec" "path/filepath" "testing" "time" @@ -42,64 +44,98 @@ func TestApproverDecisionsMatchLoadedPrograms(t *testing.T) { allowed := filepath.Join(dir, "allowed.txt") require.NoError(t, os.WriteFile(allowed, []byte("x"), 0o600)) - cfg := testConfig() + // Establish first that the capture path reports this exact open with no + // approver installed. If that fails, the problem is the enter/exit + // correlation rather than the prefilter, and the second phase would + // otherwise blame the approver for it. + baseline := watchOpens(t, nil, allowed) + require.True(t, baseline.sawAllowed, + "capture never reported the open with no approver installed; pid=%d selfOpens=%d saw %q", + os.Getpid(), baseline.selfOpens, baseline.seen) + // Written as a matches pattern rather than startswith so the rewrite into // the LPM trie is covered too. plan := filter.PlanFromFilter(mustCompile(t, "evt.name = 'openat' and file.path matches '"+dir+"/*'")) + got := watchOpens(t, plan, allowed) + + require.True(t, got.sawAllowed, + "openat matching the approved pattern never reached userspace; wanted %q, selfOpens=%d saw %q, rejects %d -> %d", + allowed, got.selfOpens, got.seen, got.rejectsBefore, got.rejectsAfter) + require.False(t, got.sawDenied, "openat outside the approved pattern reached userspace") + require.Greater(t, got.rejectsAfter, got.rejectsBefore, "approver reject counter did not advance") +} + +type openWatch struct { + sawAllowed bool + sawDenied bool + seen []string + selfOpens int + rejectsBefore uint64 + rejectsAfter uint64 +} + +const deniedPath = "/etc/hostname" +// watchOpens repeatedly opens allowed and a denied path while draining events, +// returning what reached userspace. Correlating sys_enter_openat with its exit +// goes through a bounded LRU map, so on a loaded machine any single open can +// lose its scratch entry and arrive with no path at all. Retrying keeps the +// assertions about the approver rather than about that. +func watchOpens(t *testing.T, plan *filter.ApproverPlan, allowed string) openWatch { + t.Helper() + cfg := testConfig() es := NewEventSource(ps.NewSnapshotter(), cfg, nil, plan).(*EventSource) require.NoError(t, es.Open(cfg)) - t.Cleanup(func() { _ = es.Close() }) + defer func() { _ = es.Close() }() - before := es.loader.approverRejects() - touch := func(path string) { - if f, err := os.Open(path); err == nil { - _ = f.Close() - } - } + w := openWatch{seen: make([]string, 0, 16), rejectsBefore: es.loader.approverRejects()} - // Keep generating attempts while draining. Correlating sys_enter_openat - // with its exit goes through a bounded LRU map, so on a loaded machine any - // single open can lose its scratch entry and arrive with no path at all. - // Retrying makes the assertion about the approver rather than about that. - attempts := time.NewTicker(100 * time.Millisecond) + attempts := time.NewTicker(200 * time.Millisecond) defer attempts.Stop() - touch(allowed) - touch("/etc/hostname") + touch := func() { openFromChild(t, allowed) } + touch() - deadline := time.Now().Add(30 * time.Second) - var sawAllowed, sawRejectedPath bool - seen := make([]string, 0, 16) - for time.Now().Before(deadline) && !sawAllowed { + deadline := time.Now().Add(20 * time.Second) + for time.Now().Before(deadline) && !w.sawAllowed { select { case evt := <-es.Events(): if evt.Type != event.Openat { continue } path := evt.GetParamAsString(params.FilePath) - if len(seen) < cap(seen) { - seen = append(seen, path) + if evt.PID == uint64(os.Getpid()) { + w.selfOpens++ + } + if len(w.seen) < cap(w.seen) { + w.seen = append(w.seen, fmt.Sprintf("pid=%d sys=%d %s", + evt.PID, evt.GetParamAsUint32(params.SyscallID), path)) } switch path { case allowed: - sawAllowed = true - case "/etc/hostname": - sawRejectedPath = true + w.sawAllowed = true + case deniedPath: + w.sawDenied = true } case err := <-es.Errors(): t.Fatalf("event source error: %v", err) case <-attempts.C: - touch(allowed) - touch("/etc/hostname") + touch() } } + w.rejectsAfter = es.loader.approverRejects() + return w +} - require.True(t, sawAllowed, - "openat matching the approved pattern never reached userspace; wanted %q, saw %q, rejects %d -> %d", - allowed, seen, before, es.loader.approverRejects()) - require.False(t, sawRejectedPath, "openat outside the approved pattern reached userspace") - require.Greater(t, es.loader.approverRejects(), before, "approver reject counter did not advance") +// openFromChild opens the two paths from a short-lived child rather than from +// the test process. Syscall tracepoints did not report this process's own opens +// on every runner, while child processes are reported reliably, which is also +// how the other privileged tests here drive syscalls. +func openFromChild(t *testing.T, allowed string) { + t.Helper() + cmd := exec.Command("/bin/sh", "-c", "cat -- \"$1\" >/dev/null 2>&1; cat -- \"$2\" >/dev/null 2>&1", + "sh", allowed, deniedPath) + _ = cmd.Run() } func TestApproverGenerationFlipAndFailedReload(t *testing.T) { diff --git a/pkg/filter/approver_fuzz_linux_test.go b/pkg/filter/approver_fuzz_linux_test.go index 6e64728c0..664bed6da 100644 --- a/pkg/filter/approver_fuzz_linux_test.go +++ b/pkg/filter/approver_fuzz_linux_test.go @@ -50,7 +50,6 @@ var fuzzExprs = []string{ "evt.name = 'openat' and file.path != '/tmp/x'", "evt.name = 'openat' and not (file.path = '/tmp/x')", "evt.name = 'openat' and (ps.pid = 1 or file.path = '/tmp/x')", - "evt.name = 'openat' and file.path matches '/tmp/*'", "evt.name = 'openat' and ps.name = 'bash'", "file.path startswith '/tmp'", "ps.pid = 42", diff --git a/pkg/filter/approver_linux_test.go b/pkg/filter/approver_linux_test.go index 0eaf07089..e970c24cf 100644 --- a/pkg/filter/approver_linux_test.go +++ b/pkg/filter/approver_linux_test.go @@ -64,26 +64,17 @@ func TestExtractPortList(t *testing.T) { } func TestExtractUnsupportedShapesDefaultAllow(t *testing.T) { - cases := []string{ + for _, expr := range []string{ "evt.name = 'openat' and file.path != '/etc/passwd'", "evt.name = 'openat' and not (file.path = '/etc/passwd')", "evt.name = 'openat' and (ps.pid = 1 or file.path = '/tmp/x')", - "evt.name = 'openat' and file.path matches '/tmp/*'", "evt.name = 'openat' and ps.pid > 1", "evt.name = 'openat' and lower(file.path) = '/tmp/x'", - `sequence -|evt.name = 'execve'| -|evt.name = 'connect'|`, - } - for _, expr := range cases { - f := compileApprover(t, expr) - plan := PlanFromFilter(f) - assert.True(t, plan.Policy(event.Openat).DefaultAllow || plan.Policy(event.Connect).DefaultAllow || plan.Policy(event.Execve).DefaultAllow, expr) + } { + plan := PlanFromFilter(compileApprover(t, expr)) + assert.True(t, plan.Policy(event.Openat).DefaultAllow, expr) } - orPlan := PlanFromFilter(compileApprover(t, "evt.name = 'openat' and (ps.pid = 1 or file.path = '/tmp/x')")) - assert.True(t, orPlan.Policy(event.Openat).DefaultAllow) - seqPlan := PlanFromFilter(compileApprover(t, `sequence |evt.name = 'execve'| |evt.name = 'connect'|`)) @@ -91,6 +82,24 @@ func TestExtractUnsupportedShapesDefaultAllow(t *testing.T) { assert.True(t, seqPlan.Policy(event.Connect).DefaultAllow) } +// A list of literal paths needs no wildcard machinery: every element is an +// exact key, so the whole condition resolves in the kernel's hash lookup. +func TestExtractFilePathList(t *testing.T) { + f := compileApprover(t, "evt.name = 'openat' and file.path in ('/etc/passwd', '/etc/shadow')") + ex := f.(ApproverProvider).ApproverExtraction() + require.False(t, ex.Unsupported) + assert.Equal(t, []string{"/etc/passwd", "/etc/shadow"}, ex.FileExact) + assert.Empty(t, ex.FilePrefix) + + plan := PlanFromFilter(f) + pol := plan.Policy(event.Openat) + require.False(t, pol.DefaultAllow) + assert.True(t, pol.RequireFilename) + assert.True(t, plan.Allows(Sample{Type: event.Openat, Filename: "/etc/passwd"})) + assert.True(t, plan.Allows(Sample{Type: event.Openat, Filename: "/etc/shadow"})) + assert.False(t, plan.Allows(Sample{Type: event.Openat, Filename: "/etc/hosts"})) +} + // ps.name is snapshot state while the kernel can only read the live task comm, // so a process name predicate must never narrow the in-kernel prefilter. func TestProcessNameIsNotExtractable(t *testing.T) {