From 4f1925629892bc35c31323c7e28b20ef9827e5aa Mon Sep 17 00:00:00 2001 From: Andrew LeFevre Date: Wed, 24 Jun 2026 14:07:01 -0400 Subject: [PATCH] support disk events on Linux kernel 7.0+ by conditionally hooking do_file_open (#67650) * support disk events on Linux kernel 7.0+ by conditionally hooking do_file_open * default to do_file_open --- bpf/enhancedrecording/disk.bpf.c | 6 ++-- lib/bpf/disk.go | 53 +++++++++++++++++++++++++++++-- lib/bpf/disk_arm64_bpfel.go | 6 ++-- lib/bpf/disk_arm64_bpfel.o | Bin 35840 -> 35840 bytes lib/bpf/disk_x86_bpfel.go | 6 ++-- lib/bpf/disk_x86_bpfel.o | Bin 36664 -> 36664 bytes lib/srv/bpf_test.go | 3 +- 7 files changed, 60 insertions(+), 14 deletions(-) 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 5d252166838072a43d343c011b62ddcff5e65450..a05da3a2c1b90cd64ef1076886f5fa94bda0f51e 100644 GIT binary patch delta 99 zcmZpe!PGE=X~Xvd$<+A#g4DeD)QZd!hBOeVpOPP+mYI_}S)fpoF?F+6VICi2#papy zp6raNlOMN5Ob%+7m~7fEusOLsmXWb=^1%-K$qk(nlO;Me82cwXcG@#`Z*J_YX956* CekL&h delta 106 zcmZpe!PGE=X~Xvd$%6R&g4DeD)QZd!hBOeVpOPP+mYGv9S)fpov0$@SVICi2|K^$X zp6rYTlOMN5a3ibHZ&%rz)gH#k*fIHFhdpDs|rVR!qjH#0iOT?v9 zR&2i5NJ81^c4 delta 113 zcmdlnk7>s|rVR!qj0KYoOT?uM;`0kq^B6MoN)(&|+~Na*{M|KD^5fGoa|$*mm*ny> z_HVw}