Skip to content

Commit 7fc93bd

Browse files
authored
[CWS-6123] Implement pivot_root (#47935)
### What does this PR do? Implement the pivot_root syscall ### Motivation When containers are spawned and create their mounts, it uses pivot_root to pivot the mounted mountpoint to the root of the mount namespace. This wasn't being tracked and was creating erroneous mountpoints in our events. ### Describe how you validated your changes * KMT tests * Deployed on a cluster Co-authored-by: marcio.kovags <marcio.kovags@datadoghq.com>
1 parent ab756a1 commit 7fc93bd

File tree

19 files changed

+206
-12
lines changed

19 files changed

+206
-12
lines changed

pkg/security/ebpf/c/include/constants/enums.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ enum event_type
7474
FAILED_DNS,
7575
EVENT_TRACER_MEMFD_CREATE,
7676
EVENT_TRACER_MEMFD_SEAL,
77+
EVENT_PIVOT_ROOT,
7778
EVENT_NOP,
7879
EVENT_MAX, // has to be the last one
7980

@@ -260,6 +261,7 @@ enum mount_source_t
260261
SOURCE_FSMOUNT,
261262
SOURCE_OPEN_TREE,
262263
SOURCE_MOVE_MOUNT,
264+
SOURCE_PIVOT_ROOT,
263265
};
264266

265267
#endif

pkg/security/ebpf/c/include/helpers/events_predicates.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,23 @@ static int __attribute__((always_inline)) credentials_predicate(u64 type) {
2929
}
3030

3131
static int __attribute__((always_inline)) mountpoint_predicate(u64 type) {
32-
return type == EVENT_MOUNT || type == EVENT_UNSHARE_MNTNS || type == EVENT_OPEN_TREE || type == EVENT_MOVE_MOUNT;
32+
return type == EVENT_MOUNT || type == EVENT_UNSHARE_MNTNS || type == EVENT_OPEN_TREE || type == EVENT_MOVE_MOUNT || type == EVENT_PIVOT_ROOT;
3333
}
3434

3535
static int __attribute__((always_inline)) mount_or_open_tree(u64 type) {
3636
return type == EVENT_MOUNT || type == EVENT_OPEN_TREE;
3737
}
3838

3939
static int __attribute__((always_inline)) unshare_or_move_mount(u64 type) {
40-
return type == EVENT_UNSHARE_MNTNS || type == EVENT_MOVE_MOUNT;
40+
return type == EVENT_UNSHARE_MNTNS || type == EVENT_MOVE_MOUNT || type == EVENT_PIVOT_ROOT;
4141
}
4242

4343
static int __attribute__((always_inline)) mount_or_move_mount(u64 type) {
4444
return type == EVENT_MOUNT || type == EVENT_MOVE_MOUNT;
4545
}
4646

4747
static int __attribute__((always_inline)) unshare_or_open_tree_or_move_mount(u64 type) {
48-
return type == EVENT_UNSHARE_MNTNS || type == EVENT_OPEN_TREE || type == EVENT_MOVE_MOUNT;
48+
return type == EVENT_UNSHARE_MNTNS || type == EVENT_OPEN_TREE || type == EVENT_MOVE_MOUNT || type == EVENT_PIVOT_ROOT;
4949
}
5050

5151
#endif

pkg/security/ebpf/c/include/hooks/all.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "mprotect.h"
2020
#include "namespaces.h"
2121
#include "open.h"
22+
#include "pivot_root.h"
2223
#include "procfs.h"
2324
#include "ptrace.h"
2425
#include "raw_syscalls.h"

pkg/security/ebpf/c/include/hooks/mount.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ int __attribute__((always_inline)) dr_mount_stage_two_callback(void *ctx) {
259259
return 0;
260260
}
261261

262-
if (syscall->type == EVENT_MOUNT || syscall->type == EVENT_OPEN_TREE || syscall->type == EVENT_MOVE_MOUNT) {
262+
if (syscall->type == EVENT_MOUNT || syscall->type == EVENT_OPEN_TREE || syscall->type == EVENT_MOVE_MOUNT || syscall->type == EVENT_PIVOT_ROOT) {
263263
struct mount_event_t event = {
264264
.syscall.retval = 0,
265265
.syscall_ctx.id = syscall->ctx_id,
@@ -284,6 +284,11 @@ int __attribute__((always_inline)) dr_mount_stage_two_callback(void *ctx) {
284284
event.source = SOURCE_MOVE_MOUNT;
285285
}
286286
}
287+
if (syscall->type == EVENT_PIVOT_ROOT) {
288+
event.source = SOURCE_PIVOT_ROOT;
289+
send_event(ctx, EVENT_PIVOT_ROOT, event);
290+
return 0;
291+
}
287292
if (syscall->type == EVENT_MOVE_MOUNT) {
288293
send_event(ctx, EVENT_MOVE_MOUNT, event);
289294
return 0;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef _HOOKS_PIVOT_ROOT_H_
2+
#define _HOOKS_PIVOT_ROOT_H_
3+
4+
#include "constants/syscall_macro.h"
5+
#include "helpers/syscalls.h"
6+
7+
HOOK_SYSCALL_ENTRY0(pivot_root) {
8+
struct syscall_cache_t syscall = {
9+
.type = EVENT_PIVOT_ROOT,
10+
};
11+
12+
cache_syscall(&syscall);
13+
14+
return 0;
15+
}
16+
17+
int __attribute__((always_inline)) sys_pivot_root_ret(void *ctx, int retval) {
18+
pop_syscall(EVENT_PIVOT_ROOT);
19+
return 0;
20+
}
21+
22+
HOOK_SYSCALL_EXIT(pivot_root) {
23+
int retval = SYSCALL_PARMRET(ctx);
24+
return sys_pivot_root_ret(ctx, retval);
25+
}
26+
27+
TAIL_CALL_TRACEPOINT_FNC(handle_sys_pivot_root_exit, struct tracepoint_raw_syscalls_sys_exit_t *args) {
28+
return sys_pivot_root_ret(args, args->ret);
29+
}
30+
31+
#endif

pkg/security/ebpf/c/include/maps.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ BPF_PROG_ARRAY(dentry_resolver_tracepoint_callbacks, EVENT_MAX)
144144
BPF_PROG_ARRAY(dentry_resolver_kprobe_or_fentry_progs, 6)
145145
BPF_PROG_ARRAY(dentry_resolver_tracepoint_progs, 3)
146146
BPF_PROG_ARRAY(classifier_router, 10)
147-
BPF_PROG_ARRAY(sys_exit_progs, 64)
147+
BPF_PROG_ARRAY(sys_exit_progs, EVENT_MAX)
148148
BPF_PROG_ARRAY(raw_packet_classifier_router, 32)
149149
BPF_PROG_ARRAY(flush_network_stats_progs, 2)
150150
BPF_PROG_ARRAY(open_ret_progs, 1)

pkg/security/ebpf/probes/event_types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ func GetSelectorsPerEventType(hasFentry bool, hasCgroupSocket bool) map[eval.Eve
265265
&manager.BestEffort{Selectors: ExpandSyscallProbesSelector(SecurityAgentUID, "move_mount", hasFentry, EntryAndExit, false)},
266266
&manager.BestEffort{Selectors: ExpandSyscallProbesSelector(SecurityAgentUID, "umount", hasFentry, Exit)},
267267
&manager.OneOf{Selectors: ExpandSyscallProbesSelector(SecurityAgentUID, "unshare", hasFentry, EntryAndExit)},
268+
&manager.BestEffort{Selectors: ExpandSyscallProbesSelector(SecurityAgentUID, "pivot_root", hasFentry, EntryAndExit)},
268269
&manager.OneOf{Selectors: []manager.ProbesSelector{
269270
hookFunc("hook_attach_mnt"),
270271
hookFunc("hook___attach_mnt"),

pkg/security/ebpf/probes/mount.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,5 +122,11 @@ func getMountProbes(fentry bool) []*manager.Probe {
122122
},
123123
SyscallFuncName: "move_mount",
124124
}, fentry, EntryAndExit)...)
125+
mountProbes = append(mountProbes, ExpandSyscallProbes(&manager.Probe{
126+
ProbeIdentificationPair: manager.ProbeIdentificationPair{
127+
UID: SecurityAgentUID,
128+
},
129+
SyscallFuncName: "pivot_root",
130+
}, fentry, EntryAndExit)...)
125131
return mountProbes
126132
}

pkg/security/ebpf/probes/raw_sys_exit.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,5 +226,12 @@ func getSysExitTailCallRoutes() []manager.TailCallRoute {
226226
EBPFFuncName: tailCallTracepointFnc("handle_sys_prctl_exit"),
227227
},
228228
},
229+
{
230+
ProgArrayName: "sys_exit_progs",
231+
Key: uint32(model.PivotRootEventType),
232+
ProbeIdentificationPair: manager.ProbeIdentificationPair{
233+
EBPFFuncName: tailCallTracepointFnc("handle_sys_pivot_root_exit"),
234+
},
235+
},
229236
}
230237
}

pkg/security/probe/probe_ebpf.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,7 +1240,7 @@ func (p *EBPFProbe) handleRegularEvent(event *model.Event, offset int, dataLen u
12401240
eventType := event.GetEventType()
12411241
switch eventType {
12421242

1243-
case model.FileMountEventType, model.FileMoveMountEventType:
1243+
case model.FileMountEventType, model.FileMoveMountEventType, model.PivotRootEventType:
12441244
if !p.regularUnmarshalEvent(&event.Mount, eventType, offset, dataLen, data) {
12451245
return false
12461246
}
@@ -2310,7 +2310,7 @@ func (p *EBPFProbe) handleNewMount(ev *model.Event, m *model.Mount) error {
23102310
// so we remove all dentry entries belonging to the mountID.
23112311
p.Resolvers.DentryResolver.DelCacheEntriesForMountID(m.MountID)
23122312

2313-
if !m.Detached && ev.GetEventType() != model.FileMoveMountEventType {
2313+
if !m.Detached && ev.GetEventType() != model.FileMoveMountEventType && ev.GetEventType() != model.PivotRootEventType {
23142314
// Resolve mount point
23152315
if err := p.Resolvers.PathResolver.SetMountPoint(ev, m); err != nil {
23162316
return fmt.Errorf("failed to set mount point: %w", err)
@@ -2323,7 +2323,7 @@ func (p *EBPFProbe) handleNewMount(ev *model.Event, m *model.Mount) error {
23232323
}
23242324

23252325
var err error
2326-
if ev.GetEventType() == model.FileMoveMountEventType {
2326+
if ev.GetEventType() == model.FileMoveMountEventType || ev.GetEventType() == model.PivotRootEventType {
23272327
err = p.Resolvers.MountResolver.InsertMoved(*m)
23282328
} else {
23292329
err = p.Resolvers.MountResolver.Insert(*m)

0 commit comments

Comments
 (0)