Skip to content

Commit

Permalink
detect container init to clear mntns
Browse files Browse the repository at this point in the history
  • Loading branch information
mhils committed Dec 13, 2024
1 parent 39a2f82 commit f1ca767
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 0 deletions.
34 changes: 34 additions & 0 deletions internal/pkg/daemon/bpfrecorder/bpf/recorder.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define EVENT_TYPE_APPARMOR_FILE 2
#define EVENT_TYPE_APPARMOR_SOCKET 3
#define EVENT_TYPE_APPARMOR_CAP 4
#define EVENT_TYPE_CLEAR_MNTNS 5

#define FLAG_READ 0x1
#define FLAG_WRITE 0x2
Expand Down Expand Up @@ -51,6 +52,8 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL";
#define unlikely(x) __builtin_expect((x), 0)
#endif

#define trace_hook(...) bpf_printk(__VA_ARGS__)

// Track syscalls for each mtnns
struct {
__uint(type, BPF_MAP_TYPE_HASH);
Expand Down Expand Up @@ -93,6 +96,7 @@ typedef struct __attribute__((__packed__)) event_data {
const volatile char filter_name[MAX_COMM_LEN] = {};
const volatile u32 exclude_mntns = 0;

static const char RUNC_DONE[] = "runc:[2:INIT]";
static const bool TRUE = true;
static inline bool has_filter();
static inline bool matches_filter(char * comm);
Expand Down Expand Up @@ -322,6 +326,36 @@ int BPF_KPROBE(cap_capable)
return 0;
}

SEC("tracepoint/sched/sched_prepare_exec")
int sched_prepare_exec(struct trace_event_raw_sched_process_exec * ctx)
{
u32 mntns = get_mntns();
if (!mntns)
return 0;
char comm[TASK_COMM_LEN] = {};
bpf_get_current_comm(comm, sizeof(comm));
// trace_hook("sched_prepare_exec mntns=%u comm=%s", mntns, comm);

for (int i = 0; i < sizeof(RUNC_DONE); i++) {
if (comm[i] != RUNC_DONE[i]) {
return 0;
}
}

trace_hook("clearing mount namespace: %u", mntns);

bpf_map_delete_elem(&mntns_syscalls, &mntns);
event_data_t * event = bpf_ringbuf_reserve(&events, sizeof(event_data_t), 0);
if (event) {
event->pid = bpf_get_current_pid_tgid() >> 32;
event->mntns = mntns;
event->type = EVENT_TYPE_CLEAR_MNTNS;
bpf_ringbuf_submit(event, 0);
}

return 0;
}

SEC("tracepoint/sched/sched_process_exec")
int sched_process_exec(struct trace_event_raw_sched_process_exec * ctx)
{
Expand Down
4 changes: 4 additions & 0 deletions internal/pkg/daemon/bpfrecorder/bpfrecorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const (
eventTypeAppArmorFile int = 2
eventTypeAppArmorSocket int = 3
eventTypeAppArmorCap int = 4
eventTypeClearMntns int = 5
)

// BpfRecorder is the main structure of this package.
Expand Down Expand Up @@ -409,6 +410,7 @@ func (b *BpfRecorder) getMntnsForProfile(profile string) (uint32, bool) {

var baseHooks = []string{
"sys_enter",
"sched_prepare_exec",
"sched_process_exec",
"sched_process_exit",
}
Expand Down Expand Up @@ -662,6 +664,8 @@ func (b *BpfRecorder) handleEvent(eventBytes []byte) {
b.AppArmor.handleSocketEvent(&event)
case uint8(eventTypeAppArmorCap):
b.AppArmor.handleCapabilityEvent(&event)
case uint8(eventTypeClearMntns):
b.AppArmor.clearMntns(&event)
}
}

Expand Down
21 changes: 21 additions & 0 deletions internal/pkg/daemon/bpfrecorder/bpfrecorder_apparmor.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,27 @@ func (b *AppArmorRecorder) handleCapabilityEvent(capEvent *bpfEvent) {
b.recordedCapabilities[mid] = append(b.recordedCapabilities[mid], requestedCap)
}

// Delete all data recorded for a particular mount namespace.
//
// The recorder triggers this after container initialization to make sure that
// permissions needed for setup are not included in the final profile.
func (b *AppArmorRecorder) clearMntns(event *bpfEvent) {
// Everything we captured so far is container initialization.
// Let's get rid of it.
b.lockRecordedFiles.Lock()
defer b.lockRecordedFiles.Unlock()
b.lockRecordedCapabilities.Lock()
defer b.lockRecordedCapabilities.Unlock()
b.lockRecordedSocketsUse.Lock()
defer b.lockRecordedSocketsUse.Unlock()

mntns := mntnsID(event.Mntns)
log.Printf("Clearing mntns: %d\n", mntns)
delete(b.recordedFiles, mntns)
delete(b.recordedCapabilities, mntns)
delete(b.recordedSocketsUse, mntns)
}

func (b *AppArmorRecorder) GetKnownMntns() []mntnsID {
b.lockRecordedFiles.Lock()
defer b.lockRecordedFiles.Unlock()
Expand Down

0 comments on commit f1ca767

Please sign in to comment.