Skip to content

Commit 1bb7264

Browse files
capabilities: fix: raise caps ring for privileged operations (#2280)
1 parent 69c472b commit 1bb7264

File tree

3 files changed

+99
-64
lines changed

3 files changed

+99
-64
lines changed

pkg/ebpf/events_processor.go

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func (t *Tracee) processEvent(event *trace.Event) error {
5555
switch eventId {
5656

5757
case events.VfsWrite, events.VfsWritev, events.KernelWrite:
58-
//capture written files
58+
// capture written files
5959
if t.config.Capture.FileWrite {
6060
filePath, err := parse.ArgStringVal(event, "pathname")
6161
if err != nil {
@@ -90,33 +90,33 @@ func (t *Tracee) processEvent(event *trace.Event) error {
9090
}
9191

9292
case events.SchedProcessExec:
93-
//update the process tree with correct comm name
93+
// update the process tree with correct command name
9494
if t.config.ProcessInfo {
9595
processData, err := t.procInfo.GetElement(event.HostProcessID)
9696
if err == nil {
9797
processData.Comm = event.ProcessName
9898
t.procInfo.UpdateElement(event.HostProcessID, processData)
9999
}
100100
}
101-
102-
//cache this pid by it's mnt ns
101+
// cache this pid by it's mnt ns
103102
if event.ProcessID == 1 {
104103
t.pidsInMntns.ForceAddBucketItem(uint32(event.MountNS), uint32(event.HostProcessID))
105104
} else {
106105
t.pidsInMntns.AddBucketItem(uint32(event.MountNS), uint32(event.HostProcessID))
107106
}
108-
//capture executed files
107+
// capture executed files
109108
if t.config.Capture.Exec || t.config.Output.ExecHash {
110109
filePath, err := parse.ArgStringVal(event, "pathname")
111110
if err != nil {
112111
return fmt.Errorf("error parsing sched_process_exec args: %v", err)
113112
}
114-
// path should be absolute, except for e.g memfd_create files
113+
// Should be absolute path, except for e.g memfd_create files
115114
if filePath == "" || filePath[0] != '/' {
116115
return nil
117116
}
118-
119-
// try to access the root fs via another process in the same mount namespace (since the current process might have already died)
117+
// try to access the root fs via another process in the same mount
118+
// namespace (as the process from the current event might have
119+
// already died)
120120
pids := t.pidsInMntns.GetBucket(uint32(event.MountNS))
121121
for _, pid := range pids { // will break on success
122122
err = nil
@@ -132,51 +132,61 @@ func (t *Tracee) processEvent(event *trace.Event) error {
132132
containerId = "host"
133133
}
134134
capturedFileID := fmt.Sprintf("%s:%s", containerId, sourceFilePath)
135+
// capture exec'ed files ?
135136
if t.config.Capture.Exec {
136137
destinationDirPath := containerId
137138
if err := utils.MkdirAtExist(t.outDir, destinationDirPath, 0755); err != nil {
138139
return err
139140
}
140141
destinationFilePath := filepath.Join(destinationDirPath, fmt.Sprintf("exec.%d.%s", event.Timestamp, filepath.Base(filePath)))
141-
142142
// create an in-memory profile
143143
if t.config.Capture.Profile {
144144
t.updateProfile(fmt.Sprintf("%s:%d", filepath.Join(destinationDirPath, fmt.Sprintf("exec.%s", filepath.Base(filePath))), castedSourceFileCtime), uint64(event.Timestamp))
145145
}
146-
147-
//don't capture same file twice unless it was modified
146+
// don't capture same file twice unless it was modified
148147
lastCtime, ok := t.capturedFiles[capturedFileID]
149148
if !ok || lastCtime != castedSourceFileCtime {
150-
//capture
151-
err = utils.CopyRegularFileByRelativePath(sourceFilePath, t.outDir, destinationFilePath)
149+
150+
// capture (ring1)
151+
err = t.capabilities.Required(func() error {
152+
return utils.CopyRegularFileByRelativePath(
153+
sourceFilePath,
154+
t.outDir,
155+
destinationFilePath,
156+
)
157+
})
152158
if err != nil {
153159
return err
154160
}
155-
//mark this file as captured
161+
162+
// mark this file as captured
156163
t.capturedFiles[capturedFileID] = castedSourceFileCtime
157164
}
158165
}
159-
166+
// check exec'ed hash ?
160167
if t.config.Output.ExecHash {
161168
var hashInfoObj fileExecInfo
162169
var currentHash string
163170
hashInfoInterface, ok := t.fileHashes.Get(capturedFileID)
164-
165-
// cast to fileExecInfo
166171
if ok {
167172
hashInfoObj = hashInfoInterface.(fileExecInfo)
168173
}
169-
// Check if cache can be used
174+
// check if cache can be used
170175
if ok && hashInfoObj.LastCtime == castedSourceFileCtime {
171176
currentHash = hashInfoObj.Hash
172177
} else {
173-
currentHash, err = computeFileHashAtPath(sourceFilePath)
174-
if err == nil {
175-
hashInfoObj = fileExecInfo{castedSourceFileCtime, currentHash}
176-
t.fileHashes.Add(capturedFileID, hashInfoObj)
177-
}
178-
}
179178

179+
// ring1
180+
t.capabilities.Required(func() error {
181+
currentHash, err = computeFileHashAtPath(sourceFilePath)
182+
if err == nil {
183+
hashInfoObj = fileExecInfo{castedSourceFileCtime, currentHash}
184+
t.fileHashes.Add(capturedFileID, hashInfoObj)
185+
}
186+
return nil
187+
})
188+
189+
}
180190
event.Args = append(event.Args, trace.Argument{
181191
ArgMeta: trace.ArgMeta{Name: "sha256", Type: "const char*"},
182192
Value: currentHash,
@@ -189,6 +199,7 @@ func (t *Tracee) processEvent(event *trace.Event) error {
189199
}
190200
return err
191201
}
202+
192203
case events.SchedProcessExit:
193204
if t.config.ProcessInfo {
194205
if t.config.Capture.NetPerProcess {
@@ -200,6 +211,7 @@ func (t *Tracee) processEvent(event *trace.Event) error {
200211

201212
go t.deleteProcInfoDelayed(event.HostThreadID)
202213
}
214+
203215
case events.SchedProcessFork:
204216
if t.config.ProcessInfo {
205217
hostTid, err := parse.ArgInt32Val(event, "child_tid")
@@ -246,6 +258,7 @@ func (t *Tracee) processEvent(event *trace.Event) error {
246258
}
247259
t.procInfo.UpdateElement(int(hostTid), processData)
248260
}
261+
249262
case events.CgroupMkdir:
250263
cgroupId, err := parse.ArgUint64Val(event, "cgroup_id")
251264
if err != nil {
@@ -286,8 +299,9 @@ func (t *Tracee) processEvent(event *trace.Event) error {
286299
}
287300
t.containers.CgroupRemove(cgroupId, hId)
288301

289-
// in case FinitModule and InitModule occurs it means that a kernel module was loaded
290-
// and we will want to check if it hooked the syscall table and seq_ops
302+
// In case FinitModule and InitModule occurs, it means that a kernel module
303+
// was loaded and tracee needs to check if it hooked the syscall table and
304+
// seq_ops
291305
case events.DoInitModule:
292306
_, ok1 := t.events[events.HookedSyscalls]
293307
_, ok2 := t.events[events.HookedSeqOps]
@@ -330,6 +344,7 @@ func (t *Tracee) processEvent(event *trace.Event) error {
330344
}
331345
}
332346
event.Args[0].Value = hookedFops
347+
333348
case events.PrintNetSeqOps, events.PrintSyscallTable:
334349
// Initial event - no need to process
335350
if event.Timestamp == 0 {
@@ -339,10 +354,10 @@ func (t *Tracee) processEvent(event *trace.Event) error {
339354
if err != nil {
340355
return fmt.Errorf("failed to apply invoke context on %s event: %s", event.EventName, err)
341356
}
342-
343-
// this was previously event = &withInvokingContext
344-
// however, if applied as such, withInvokingContext will go out of scope and the reference will be moved back
345-
// as such we apply the value internally and not through a referene switch
357+
// This was previously event = &withInvokingContext. However, if applied
358+
// as such, withInvokingContext will go out of scope and the reference
359+
// will be moved back as such we apply the value internally and not
360+
// through a referene switch
346361
(*event) = withInvokingContext
347362
}
348363

pkg/ebpf/initialization/ksymbols.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package initialization
22

33
import (
4+
"unsafe"
5+
46
"github.com/aquasecurity/libbpfgo"
57
"github.com/aquasecurity/libbpfgo/helpers"
6-
"unsafe"
78
)
89

910
var maxKsymNameLen = 64 // Most match the constant in the bpf code
@@ -33,11 +34,14 @@ func SendKsymbolsToMap(bpfKsymsMap *libbpfgo.BPFMap, ksymbols map[string]*helper
3334
return nil
3435
}
3536

36-
// ValidateKsymbolsTable check if the addresses in the table are valid by checking a specific symbol address.
37-
// The reason for the addresses to be invalid is if the capabilities required to read the kallsyms file are not given.
38-
// The chosen symbol used here is "security_file_open" because it is a must-have symbol for tracee to run.
37+
// ValidateKsymbolsTable checks if the addresses in the table are valid by
38+
// checking a specific symbol address. The reason for the addresses to be
39+
// invalid is if the capabilities required to read the kallsyms file are not
40+
// given. The chosen symbol used here is "security_file_open" because it is a
41+
// must-have symbol for tracee to run.
3942
func ValidateKsymbolsTable(ksyms *helpers.KernelSymbolTable) bool {
40-
if sym, err := ksyms.GetSymbolByName(globalSymbolOwner, "security_file_open"); err != nil || sym.Address == 0 {
43+
sym, err := ksyms.GetSymbolByName(globalSymbolOwner, "security_file_open")
44+
if err != nil || sym.Address == 0 {
4145
return false
4246
}
4347
return true

pkg/ebpf/tracee.go

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"io"
1212
"net"
1313
"os"
14+
"runtime/debug"
1415
"strconv"
1516
"strings"
1617
"syscall"
@@ -375,20 +376,21 @@ func (t *Tracee) Init() error {
375376

376377
// Init kernel symbols map
377378

378-
err = t.capabilities.Requested(func() error {
379-
if initReq.kallsyms {
379+
if initReq.kallsyms {
380+
err = t.capabilities.Requested(func() error { // ring2
381+
380382
t.kernelSymbols, err = helpers.NewKernelSymbolsMap()
381383
if err != nil {
382384
t.Close()
383385
return fmt.Errorf("error creating symbols map: %v", err)
384386
}
385387
if !initialization.ValidateKsymbolsTable(t.kernelSymbols) {
386-
return fmt.Errorf("kernel symbols were not loaded currectly. " +
387-
"Make sure tracee-ebpf has the CAP_SYSLOG capability")
388+
return fmt.Errorf("kernel symbols were not loaded currectly")
388389
}
389-
}
390-
return nil
391-
}, cap.SYSLOG)
390+
return nil
391+
392+
}, cap.SYSLOG)
393+
}
392394
if err != nil {
393395
return err
394396
}
@@ -1313,24 +1315,33 @@ func (t *Tracee) Run(ctx gocontext.Context) error {
13131315

13141316
// Close cleans up created resources
13151317
func (t *Tracee) Close() {
1316-
if t.probes != nil {
1317-
err := t.probes.DetachAll()
1318-
if err != nil {
1319-
fmt.Fprintf(os.Stderr, "failed to detach probes when closing tracee: %s", err)
1318+
err := t.capabilities.Required(func() error { // ring1
1319+
1320+
if t.probes != nil {
1321+
err := t.probes.DetachAll()
1322+
if err != nil {
1323+
return fmt.Errorf("failed to detach probes when closing tracee: %s", err)
1324+
}
13201325
}
1321-
}
13221326

1323-
if t.bpfModule != nil {
1324-
t.bpfModule.Close()
1325-
}
1327+
if t.bpfModule != nil {
1328+
t.bpfModule.Close()
1329+
}
13261330

1327-
if t.containers != nil {
1328-
err := t.containers.Close()
1329-
if err != nil {
1330-
fmt.Fprintf(os.Stderr, "failed to clean containers module when closing tracee: %s", err)
1331+
if t.containers != nil {
1332+
err := t.containers.Close()
1333+
if err != nil {
1334+
return fmt.Errorf("failed to clean containers module when closing tracee: %s", err)
1335+
}
13311336
}
1337+
t.running = false
1338+
1339+
return nil
1340+
})
1341+
1342+
if err != nil {
1343+
fmt.Fprintf(os.Stderr, "%v", err)
13321344
}
1333-
t.running = false
13341345
}
13351346

13361347
func (t *Tracee) Running() bool {
@@ -1458,14 +1469,19 @@ func (t *Tracee) triggerSeqOpsIntegrityCheckCall(
14581469
}
14591470

14601471
func (t *Tracee) updateKallsyms() error {
1461-
kernelSymbols, err := helpers.NewKernelSymbolsMap()
1462-
if err != nil {
1463-
return err
1464-
}
1465-
if !initialization.ValidateKsymbolsTable(kernelSymbols) {
1466-
return errors.New("invalid ksymbol table")
1467-
}
1472+
return t.capabilities.Requested(func() error { // ring2
14681473

1469-
t.kernelSymbols = kernelSymbols
1470-
return nil
1474+
kernelSymbols, err := helpers.NewKernelSymbolsMap()
1475+
if err != nil {
1476+
return err
1477+
}
1478+
if !initialization.ValidateKsymbolsTable(kernelSymbols) {
1479+
debug.PrintStack()
1480+
return errors.New("invalid ksymbol table")
1481+
}
1482+
t.kernelSymbols = kernelSymbols
1483+
1484+
return nil
1485+
1486+
}, cap.SYSLOG)
14711487
}

0 commit comments

Comments
 (0)