diff --git a/bpf/enhancedrecording/disk.bpf.c b/bpf/enhancedrecording/disk.bpf.c index 58e877f8e57..ab66dc263c6 100644 --- a/bpf/enhancedrecording/disk.bpf.c +++ b/bpf/enhancedrecording/disk.bpf.c @@ -114,12 +114,12 @@ int BPF_PROG(security_file_open, struct file *f) return 0; } -// do_filp_open is called for all file open syscalls, but we aren't +// do_file_open is called for all file open syscalls, but we aren't // able to get a resolved path here. If opening failed early, // security_file_open will not be called so we fall back to using the // unresolved path in the emitted event. -SEC("fexit/do_filp_open") -int BPF_PROG(do_filp_open_exit, int dfd, struct filename *pathname, const struct open_flags *op, struct file *ret) +SEC("fexit/do_file_open") +int BPF_PROG(do_file_open_exit, int dfd, struct filename *pathname, const struct open_flags *op, struct file *ret) { struct task_struct *task = bpf_get_current_task_btf(); u32 session_id = task->sessionid; diff --git a/lib/bpf/disk.go b/lib/bpf/disk.go index b1338532be0..4c96782def8 100644 --- a/lib/bpf/disk.go +++ b/lib/bpf/disk.go @@ -22,10 +22,12 @@ package bpf import ( "context" + "errors" "io" "sync" "github.com/cilium/ebpf" + "github.com/cilium/ebpf/btf" "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/ringbuf" "github.com/cilium/ebpf/rlimit" @@ -36,6 +38,11 @@ import ( "github.com/gravitational/teleport/lib/observability/metrics" ) +const ( + doFilpOpenName = "do_filp_open" + doFileOpenName = "do_file_open" +) + var lostDiskEvents = prometheus.NewCounter( prometheus.CounterOpts{ Name: teleport.MetricLostDiskEvents, @@ -71,9 +78,28 @@ func startOpen(bufferSize int) (*open, error) { return nil, trace.Wrap(err) } + // The disk eBPF program hooks do_file_open by default, which was + // renamed from do_filp_open in 7.0. Check if do_file_open is available + // and use do_filp_open otherwise; don't rely on the kernel version. + attachTarget, err := findOpenAttachTarget() + if err != nil { + return nil, trace.Wrap(err) + } + var objs diskObjects - if err := loadDiskObjects(&objs, nil); err != nil { - return nil, trace.Wrap(err, "loading disk objects: %v", err) + spec, err := loadDisk() + if err != nil { + return nil, trace.Wrap(err, "reading disk objects") + } + + p, ok := spec.Programs["do_file_open_exit"] + if !ok { + return nil, trace.NotFound("do_file_open_exit not found in disk objects") + } + p.AttachTo = attachTarget + + if err := spec.LoadAndAssign(&objs, nil); err != nil { + return nil, trace.Wrap(err, "loading disk objects") } lostCtr, err := NewCounter(objs.LostCounter, objs.LostDoorbell, lostDiskEvents) @@ -91,7 +117,7 @@ func startOpen(bufferSize int) (*open, error) { attachType: ebpf.AttachTraceFEntry, }, { - prog: objs.DoFilpOpenExit, + prog: objs.DoFileOpenExit, attachType: ebpf.AttachTraceFExit, }, } @@ -124,6 +150,27 @@ func startOpen(bufferSize int) (*open, error) { return o, nil } +func findOpenAttachTarget() (string, error) { + kspec, err := btf.LoadKernelSpec() + if err != nil { + return "", trace.Wrap(err, "loading kernel BTF spec") + } + + for _, target := range []string{doFileOpenName, doFilpOpenName} { + var fn *btf.Func + if err := kspec.TypeByName(target, &fn); err != nil { + if errors.Is(err, btf.ErrNotFound) { + continue + } + return "", trace.Wrap(err, "finding %s", target) + } + + return target, nil + } + + return "", trace.NotFound("do_file_open and do_filp_open not found in kernel BTF spec") +} + func (o *open) startSession(auditSessionID uint32) error { o.mtx.Lock() defer o.mtx.Unlock() diff --git a/lib/bpf/disk_arm64_bpfel.go b/lib/bpf/disk_arm64_bpfel.go index 48621f265c0..ad825a9c710 100644 --- a/lib/bpf/disk_arm64_bpfel.go +++ b/lib/bpf/disk_arm64_bpfel.go @@ -67,7 +67,7 @@ type diskSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type diskProgramSpecs struct { - DoFilpOpenExit *ebpf.ProgramSpec `ebpf:"do_filp_open_exit"` + DoFileOpenExit *ebpf.ProgramSpec `ebpf:"do_file_open_exit"` SecurityFileOpen *ebpf.ProgramSpec `ebpf:"security_file_open"` } @@ -137,13 +137,13 @@ type diskVariables struct { // // It can be passed to loadDiskObjects or ebpf.CollectionSpec.LoadAndAssign. type diskPrograms struct { - DoFilpOpenExit *ebpf.Program `ebpf:"do_filp_open_exit"` + DoFileOpenExit *ebpf.Program `ebpf:"do_file_open_exit"` SecurityFileOpen *ebpf.Program `ebpf:"security_file_open"` } func (p *diskPrograms) Close() error { return _DiskClose( - p.DoFilpOpenExit, + p.DoFileOpenExit, p.SecurityFileOpen, ) } diff --git a/lib/bpf/disk_arm64_bpfel.o b/lib/bpf/disk_arm64_bpfel.o index 5d252166838..a05da3a2c1b 100644 Binary files a/lib/bpf/disk_arm64_bpfel.o and b/lib/bpf/disk_arm64_bpfel.o differ diff --git a/lib/bpf/disk_x86_bpfel.go b/lib/bpf/disk_x86_bpfel.go index 5b87c0d9596..b90a2cf5a1c 100644 --- a/lib/bpf/disk_x86_bpfel.go +++ b/lib/bpf/disk_x86_bpfel.go @@ -67,7 +67,7 @@ type diskSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type diskProgramSpecs struct { - DoFilpOpenExit *ebpf.ProgramSpec `ebpf:"do_filp_open_exit"` + DoFileOpenExit *ebpf.ProgramSpec `ebpf:"do_file_open_exit"` SecurityFileOpen *ebpf.ProgramSpec `ebpf:"security_file_open"` } @@ -137,13 +137,13 @@ type diskVariables struct { // // It can be passed to loadDiskObjects or ebpf.CollectionSpec.LoadAndAssign. type diskPrograms struct { - DoFilpOpenExit *ebpf.Program `ebpf:"do_filp_open_exit"` + DoFileOpenExit *ebpf.Program `ebpf:"do_file_open_exit"` SecurityFileOpen *ebpf.Program `ebpf:"security_file_open"` } func (p *diskPrograms) Close() error { return _DiskClose( - p.DoFilpOpenExit, + p.DoFileOpenExit, p.SecurityFileOpen, ) } diff --git a/lib/bpf/disk_x86_bpfel.o b/lib/bpf/disk_x86_bpfel.o index f92c785cbfe..0d3b365e58b 100644 Binary files a/lib/bpf/disk_x86_bpfel.o and b/lib/bpf/disk_x86_bpfel.o differ diff --git a/lib/srv/bpf_test.go b/lib/srv/bpf_test.go index 23268b72e03..70023693feb 100644 --- a/lib/srv/bpf_test.go +++ b/lib/srv/bpf_test.go @@ -1343,7 +1343,6 @@ func runCommand(t *testing.T, srv Server, bpfSrv bpf.BPF, command string, expect scx.execRequest.SetCommand(command) clientChan, serverChan := newMockSSHChannel(t) - clientChan.Drain() t.Logf("running %q", command) @@ -1399,7 +1398,7 @@ func runCommand(t *testing.T, srv Server, bpfSrv bpf.BPF, command string, expect stdout := make([]byte, 1024) for { - _, err := serverChan.Read(stdout) + _, err := clientChan.Read(stdout) if err != nil { if errors.Is(err, io.EOF) { return