Skip to content

Commit 3233f0b

Browse files
feat(time): normalize all time to epoch
Remove all timeNormalizer object logic. Instead use simple normalization functions and normalize all timestamps in events asap: 1. Context timestamp normalization moved to decode stage 2. Relevant timestamp arguments normalized in processing stage, registered to run first.
1 parent 459a5c9 commit 3233f0b

14 files changed

+88
-129
lines changed

pkg/ebpf/capture.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/aquasecurity/tracee/pkg/bufferdecoder"
1313
"github.com/aquasecurity/tracee/pkg/errfmt"
1414
"github.com/aquasecurity/tracee/pkg/logger"
15+
"github.com/aquasecurity/tracee/pkg/time"
1516
"github.com/aquasecurity/tracee/pkg/utils"
1617
)
1718

@@ -109,7 +110,7 @@ func (t *Tracee) handleFileCaptures(ctx context.Context) {
109110
continue
110111
}
111112
// note: size of buffer will determine maximum extracted file size! (as writes from kernel are immediate)
112-
mprotectMeta.Ts = uint64(t.timeNormalizer.NormalizeTime(int(mprotectMeta.Ts)))
113+
mprotectMeta.Ts = time.BootToEpochNS(uint64(mprotectMeta.Ts))
113114
filename = fmt.Sprintf("bin.pid-%d.ts-%d", mprotectMeta.Pid, mprotectMeta.Ts)
114115
} else if meta.BinType == bufferdecoder.SendKernelModule {
115116
err = metaBuffDecoder.DecodeKernelModuleMeta(&kernelModuleMeta)

pkg/ebpf/controlplane/controller.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/aquasecurity/tracee/pkg/events"
1212
"github.com/aquasecurity/tracee/pkg/logger"
1313
"github.com/aquasecurity/tracee/pkg/proctree"
14-
traceetime "github.com/aquasecurity/tracee/pkg/time"
1514
)
1615

1716
// TODO: With the introduction of signal events, the control plane can now have a generic argument
@@ -29,7 +28,6 @@ type Controller struct {
2928
cgroupManager *containers.Containers
3029
processTree *proctree.ProcessTree
3130
enrichDisabled bool
32-
timeNormalizer traceetime.TimeNormalizer
3331
}
3432

3533
// NewController creates a new controller.
@@ -38,7 +36,6 @@ func NewController(
3836
cgroupManager *containers.Containers,
3937
enrichDisabled bool,
4038
procTree *proctree.ProcessTree,
41-
timeNormalizer traceetime.TimeNormalizer,
4239
) (*Controller, error) {
4340
var err error
4441

@@ -49,7 +46,6 @@ func NewController(
4946
cgroupManager: cgroupManager,
5047
processTree: procTree,
5148
enrichDisabled: enrichDisabled,
52-
timeNormalizer: timeNormalizer,
5349
}
5450

5551
p.signalBuffer, err = bpfModule.InitPerfBuf("signals", p.signalChan, p.lostSignalChan, 1024)

pkg/ebpf/controlplane/processes.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package controlplane
33
import (
44
"github.com/aquasecurity/tracee/pkg/events/parse"
55
"github.com/aquasecurity/tracee/pkg/proctree"
6+
"github.com/aquasecurity/tracee/pkg/time"
67
"github.com/aquasecurity/tracee/pkg/utils"
78
"github.com/aquasecurity/tracee/types/trace"
89
)
@@ -67,31 +68,36 @@ func (ctrl *Controller) procTreeForkProcessor(args []trace.Argument) error {
6768
}
6869
}
6970

71+
timestamp = time.BootToEpochNS(timestamp)
72+
childStartTime = time.BootToEpochNS(childStartTime)
73+
parentStartTime = time.BootToEpochNS(parentStartTime)
74+
leaderStartTime = time.BootToEpochNS(leaderStartTime)
75+
7076
childHash := utils.HashTaskID(uint32(childTid), childStartTime)
7177
parentHash := utils.HashTaskID(uint32(parentTid), parentStartTime)
7278
leaderHash := utils.HashTaskID(uint32(leaderTid), leaderStartTime)
7379

7480
return ctrl.processTree.FeedFromFork(
7581
proctree.ForkFeed{
76-
TimeStamp: uint64(ctrl.timeNormalizer.NormalizeTime(int(timestamp))),
82+
TimeStamp: timestamp,
7783
ChildHash: childHash,
7884
ParentHash: parentHash,
7985
LeaderHash: leaderHash,
8086
ParentTid: parentTid,
8187
ParentNsTid: parentNsTid,
8288
ParentPid: parentPid,
8389
ParentNsPid: parentNsPid,
84-
ParentStartTime: uint64(ctrl.timeNormalizer.NormalizeTime(int(parentStartTime))),
90+
ParentStartTime: parentStartTime,
8591
LeaderTid: leaderTid,
8692
LeaderNsTid: leaderNsTid,
8793
LeaderPid: leaderPid,
8894
LeaderNsPid: leaderNsPid,
89-
LeaderStartTime: uint64(ctrl.timeNormalizer.NormalizeTime(int(leaderStartTime))),
95+
LeaderStartTime: leaderStartTime,
9096
ChildTid: childTid,
9197
ChildNsTid: childNsTid,
9298
ChildPid: childPid,
9399
ChildNsPid: childNsPid,
94-
ChildStartTime: uint64(ctrl.timeNormalizer.NormalizeTime(int(childStartTime))),
100+
ChildStartTime: childStartTime,
95101
},
96102
)
97103
}
@@ -154,7 +160,7 @@ func (ctrl *Controller) procTreeExecProcessor(args []trace.Argument) error {
154160

155161
return ctrl.processTree.FeedFromExec(
156162
proctree.ExecFeed{
157-
TimeStamp: uint64(ctrl.timeNormalizer.NormalizeTime(int(timestamp))),
163+
TimeStamp: time.BootToEpochNS(timestamp),
158164
TaskHash: taskHash,
159165
ParentHash: parentHash,
160166
LeaderHash: leaderHash,
@@ -208,7 +214,7 @@ func (ctrl *Controller) procTreeExitProcessor(args []trace.Argument) error {
208214

209215
return ctrl.processTree.FeedFromExit(
210216
proctree.ExitFeed{
211-
TimeStamp: uint64(ctrl.timeNormalizer.NormalizeTime(int(timestamp))), // time of exit is already a timestamp
217+
TimeStamp: time.BootToEpochNS(timestamp), // time of exit is already a times)p
212218
TaskHash: taskHash,
213219
ParentHash: parentHash,
214220
LeaderHash: leaderHash,

pkg/ebpf/events_pipeline.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/aquasecurity/tracee/pkg/errfmt"
1414
"github.com/aquasecurity/tracee/pkg/events"
1515
"github.com/aquasecurity/tracee/pkg/logger"
16+
"github.com/aquasecurity/tracee/pkg/time"
1617
"github.com/aquasecurity/tracee/pkg/utils"
1718
"github.com/aquasecurity/tracee/types/trace"
1819
)
@@ -227,8 +228,14 @@ func (t *Tracee) decodeEvents(ctx context.Context, sourceChan chan []byte) (<-ch
227228

228229
// populate all the fields of the event used in this stage, and reset the rest
229230

230-
evt.Timestamp = int(eCtx.Ts)
231-
evt.ThreadStartTime = int(eCtx.StartTime)
231+
// normalize timestamp context fields for later use
232+
normalizedTs := time.BootToEpochNS(eCtx.Ts)
233+
normalizedThreadStartTime := time.BootToEpochNS(eCtx.StartTime)
234+
normalizedLeaderStartTime := time.BootToEpochNS(eCtx.LeaderStartTime)
235+
normalizedParentStartTime := time.BootToEpochNS(eCtx.ParentStartTime)
236+
237+
evt.Timestamp = int(normalizedTs)
238+
evt.ThreadStartTime = int(normalizedThreadStartTime)
232239
evt.ProcessorID = int(eCtx.ProcessorId)
233240
evt.ProcessID = int(eCtx.Pid)
234241
evt.ThreadID = int(eCtx.Tid)
@@ -239,8 +246,8 @@ func (t *Tracee) decodeEvents(ctx context.Context, sourceChan chan []byte) (<-ch
239246
evt.UserID = int(eCtx.Uid)
240247
evt.MountNS = int(eCtx.MntID)
241248
evt.PIDNS = int(eCtx.PidID)
242-
evt.ProcessName = string(bytes.TrimRight(eCtx.Comm[:], "\x00"))
243-
evt.HostName = string(bytes.TrimRight(eCtx.UtsName[:], "\x00"))
249+
evt.ProcessName = string(bytes.TrimRight(eCtx.Comm[:], "\x00")) // set and clean potential trailing null
250+
evt.HostName = string(bytes.TrimRight(eCtx.UtsName[:], "\x00")) // set and clean potential trailing null
244251
evt.CgroupID = uint(eCtx.CgroupID)
245252
evt.ContainerID = containerData.ID
246253
evt.Container = containerData
@@ -258,9 +265,9 @@ func (t *Tracee) decodeEvents(ctx context.Context, sourceChan chan []byte) (<-ch
258265
evt.ContextFlags = flags
259266
evt.Syscall = syscall
260267
evt.Metadata = nil
261-
evt.ThreadEntityId = utils.HashTaskID(eCtx.HostTid, eCtx.StartTime)
262-
evt.ProcessEntityId = utils.HashTaskID(eCtx.HostPid, eCtx.LeaderStartTime)
263-
evt.ParentEntityId = utils.HashTaskID(eCtx.HostPpid, eCtx.ParentStartTime)
268+
evt.ThreadEntityId = utils.HashTaskID(eCtx.HostTid, normalizedThreadStartTime)
269+
evt.ProcessEntityId = utils.HashTaskID(eCtx.HostPid, normalizedLeaderStartTime)
270+
evt.ParentEntityId = utils.HashTaskID(eCtx.HostPpid, normalizedParentStartTime)
264271

265272
// If there aren't any policies that need filtering in userland, tracee **may** skip
266273
// this event, as long as there aren't any derivatives or signatures that depend on it.
@@ -727,7 +734,7 @@ func (t *Tracee) parseArguments(e *trace.Event) error {
727734
}
728735

729736
if t.config.Output.ParseArgumentsFDs {
730-
return events.ParseArgsFDs(e, uint64(t.timeNormalizer.GetOriginalTime(e.Timestamp)), t.FDArgPathMap)
737+
return events.ParseArgsFDs(e, uint64(e.Timestamp), t.FDArgPathMap)
731738
}
732739
}
733740

pkg/ebpf/net_capture.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,6 @@ func (t *Tracee) processNetCapEvents(ctx context.Context, in <-chan *trace.Event
5959
select {
6060
case event := <-in:
6161
// TODO: Support captures pipeline in t.processEvent
62-
err := t.normalizeEventCtxTimes(event)
63-
if err != nil {
64-
t.handleError(err)
65-
t.eventsPool.Put(event)
66-
continue
67-
}
6862
t.processNetCapEvent(event)
6963
_ = t.stats.NetCapCount.Increment()
7064
t.eventsPool.Put(event)

pkg/ebpf/processor.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ func (t *Tracee) RegisterEventProcessor(id events.ID, proc func(evt *trace.Event
7878

7979
// registerEventProcessors registers all event processors, each to a specific event id.
8080
func (t *Tracee) registerEventProcessors() {
81+
//
82+
// Event Timestamps Normalization
83+
//
84+
85+
// Convert all time relate args to nanoseconds since epoch.
86+
// NOTE: Make sure to convert time related args (of your event) in here, so that
87+
// any later code has access to normalized time arguments.
88+
t.RegisterEventProcessor(events.SchedProcessFork, t.normalizeTimeArg(
89+
"start_time",
90+
"parent_start_time",
91+
"parent_process_start_time",
92+
"leader_start_time",
93+
))
94+
8195
//
8296
// Process Tree Processors
8397
//
@@ -120,15 +134,6 @@ func (t *Tracee) registerEventProcessors() {
120134
t.RegisterEventProcessor(events.PrintMemDump, t.processPrintMemDump)
121135
t.RegisterEventProcessor(events.SharedObjectLoaded, t.processSharedObjectLoaded)
122136

123-
//
124-
// Event Timestamps Normalization Processors
125-
//
126-
127-
// Convert all time relate args to nanoseconds since epoch.
128-
// NOTE: Make sure to convert time related args (of your event) in here.
129-
t.RegisterEventProcessor(events.SchedProcessFork, t.normalizeTimeArg("start_time"))
130-
t.RegisterEventProcessor(events.All, t.normalizeEventCtxTimes)
131-
132137
//
133138
// Uprobe based events processors
134139
//

pkg/ebpf/processor_funcs.go

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/aquasecurity/tracee/pkg/events/parse"
2020
"github.com/aquasecurity/tracee/pkg/filehash"
2121
"github.com/aquasecurity/tracee/pkg/logger"
22+
"github.com/aquasecurity/tracee/pkg/time"
2223
"github.com/aquasecurity/tracee/pkg/utils"
2324
"github.com/aquasecurity/tracee/types/trace"
2425
)
@@ -161,7 +162,11 @@ func (t *Tracee) processSchedProcessExec(event *trace.Event) error {
161162
}
162163
destinationFilePath := filepath.Join(
163164
destinationDirPath,
164-
fmt.Sprintf("exec.%d.%s", event.Timestamp, filepath.Base(filePath)),
165+
fmt.Sprintf(
166+
"exec.%d.%s",
167+
event.Timestamp,
168+
filepath.Base(filePath),
169+
),
165170
)
166171
// don't capture same file twice unless it was modified
167172
lastCtime, ok := t.capturedFiles[capturedFileID]
@@ -346,33 +351,21 @@ func (t *Tracee) processPrintMemDump(event *trace.Event) error {
346351
// Timing related functions
347352
//
348353

349-
// normalizeEventCtxTimes normalizes the event context timings to be relative to tracee start time
350-
// or current time in nanoseconds.
351-
func (t *Tracee) normalizeEventCtxTimes(event *trace.Event) error {
352-
eventId := events.ID(event.EventID)
353-
if eventId > events.MaxCommonID && eventId < events.MaxUserSpace {
354-
// derived events are normalized from their base event, skip the processing
355-
return nil
356-
}
357-
event.Timestamp = t.timeNormalizer.NormalizeTime(event.Timestamp)
358-
event.ThreadStartTime = t.timeNormalizer.NormalizeTime(event.ThreadStartTime)
359-
360-
return nil
361-
}
362-
363354
// normalizeTimeArg returns a processor function for some argument name
364-
// which normalizes said event arg time to be relative to tracee start time or current time.
365-
func (t *Tracee) normalizeTimeArg(argName string) func(event *trace.Event) error {
355+
// which normalizes said event arg time from boot monotonic to epoch
356+
func (t *Tracee) normalizeTimeArg(argNames ...string) func(event *trace.Event) error {
366357
return func(event *trace.Event) error {
367-
arg := events.GetArg(event, argName)
368-
if arg == nil {
369-
return errfmt.Errorf("couldn't find argument %s of event %s", argName, event.EventName)
370-
}
371-
argTime, ok := arg.Value.(uint64)
372-
if !ok {
373-
return errfmt.Errorf("argument %s of event %s is not of type uint64", argName, event.EventName)
358+
for _, argName := range argNames {
359+
arg := events.GetArg(event, argName)
360+
if arg == nil {
361+
return errfmt.Errorf("couldn't find argument %s of event %s", argName, event.EventName)
362+
}
363+
argTime, ok := arg.Value.(uint64)
364+
if !ok {
365+
return errfmt.Errorf("argument %s of event %s is not of type uint64", argName, event.EventName)
366+
}
367+
arg.Value = time.BootToEpochNS(argTime)
374368
}
375-
arg.Value = t.timeNormalizer.NormalizeTime(int(argTime))
376369
return nil
377370
}
378371
}

pkg/ebpf/processor_proctree.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,25 +75,25 @@ func (t *Tracee) procTreeForkProcessor(event *trace.Event) error {
7575

7676
return t.processTree.FeedFromFork(
7777
proctree.ForkFeed{
78-
TimeStamp: uint64(t.timeNormalizer.NormalizeTime(int(childStartTime))), // event timestamp is the same
78+
TimeStamp: childStartTime, // event timestamp is the same
7979
ChildHash: childHash,
8080
ParentHash: parentHash,
8181
LeaderHash: leaderHash,
8282
ParentTid: parentTid,
8383
ParentNsTid: parentNsTid,
8484
ParentPid: parentPid,
8585
ParentNsPid: parentNsPid,
86-
ParentStartTime: uint64(t.timeNormalizer.NormalizeTime(int(parentStartTime))),
86+
ParentStartTime: parentStartTime,
8787
LeaderTid: leaderTid,
8888
LeaderNsTid: leaderNsTid,
8989
LeaderPid: leaderPid,
9090
LeaderNsPid: leaderNsPid,
91-
LeaderStartTime: uint64(t.timeNormalizer.NormalizeTime(int(leaderStartTime))),
91+
LeaderStartTime: leaderStartTime,
9292
ChildTid: childTid,
9393
ChildNsTid: childNsTid,
9494
ChildPid: childPid,
9595
ChildNsPid: childNsPid,
96-
ChildStartTime: uint64(t.timeNormalizer.NormalizeTime(int(childStartTime))),
96+
ChildStartTime: childStartTime,
9797
},
9898
)
9999
}
@@ -153,7 +153,7 @@ func (t *Tracee) procTreeExecProcessor(event *trace.Event) error {
153153

154154
return t.processTree.FeedFromExec(
155155
proctree.ExecFeed{
156-
TimeStamp: uint64(t.timeNormalizer.NormalizeTime(int(timestamp))),
156+
TimeStamp: timestamp,
157157
TaskHash: taskHash,
158158
ParentHash: 0, // regular pipeline does not have parent hash
159159
LeaderHash: 0, // regular pipeline does not have leader hash
@@ -204,7 +204,7 @@ func (t *Tracee) procTreeExitProcessor(event *trace.Event) error {
204204

205205
return t.processTree.FeedFromExit(
206206
proctree.ExitFeed{
207-
TimeStamp: uint64(t.timeNormalizer.NormalizeTime(int(timestamp))), // time of exit is already a timestamp
207+
TimeStamp: timestamp, // time of exit is already a timestamp
208208
TaskHash: taskHash,
209209
ParentHash: 0, // regular pipeline does not have parent hash
210210
LeaderHash: 0, // regular pipeline does not have leader hash
@@ -237,7 +237,7 @@ func (t *Tracee) procTreeAddBinInfo(event *trace.Event) error {
237237
}
238238

239239
// Event timestamp is changed to relative (or not) at the end of all processors only.
240-
eventTimestamp := traceetime.NsSinceEpochToTime(uint64(t.timeNormalizer.NormalizeTime(event.Timestamp)))
240+
eventTimestamp := traceetime.NsSinceEpochToTime(uint64(event.Timestamp))
241241

242242
executable := currentProcess.GetExecutable()
243243

pkg/ebpf/tracee.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,6 @@ type Tracee struct {
125125
// This does not mean they are required for tracee to function.
126126
// TODO: remove this in favor of dependency manager nodes
127127
requiredKsyms []string
128-
// Time for normalization
129-
timeNormalizer traceetime.TimeNormalizer
130128
}
131129

132130
func (t *Tracee) Stats() *metrics.Stats {
@@ -410,8 +408,6 @@ func (t *Tracee) Init(ctx gocontext.Context) error {
410408
// time in nanoseconds when the system was booted
411409
t.bootTime = uint64(traceetime.GetBootTimeNS())
412410

413-
t.timeNormalizer = traceetime.CreateTimeNormalizerByConfig(t.bootTime)
414-
415411
// Initialize event derivation logic
416412

417413
err = t.initDerivationTable()
@@ -440,7 +436,7 @@ func (t *Tracee) Init(ctx gocontext.Context) error {
440436
proctreeConfig.ProcfsInitialization = false
441437
proctreeConfig.ProcfsQuerying = false
442438
}
443-
t.processTree, err = proctree.NewProcessTree(ctx, proctreeConfig, t.timeNormalizer)
439+
t.processTree, err = proctree.NewProcessTree(ctx, proctreeConfig)
444440
if err != nil {
445441
return errfmt.WrapError(err)
446442
}
@@ -1275,7 +1271,6 @@ func (t *Tracee) initBPF() error {
12751271
t.containers,
12761272
t.config.NoContainersEnrich,
12771273
t.processTree,
1278-
t.timeNormalizer,
12791274
)
12801275
if err != nil {
12811276
return errfmt.WrapError(err)

0 commit comments

Comments
 (0)