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
This commit is contained in:
Andrew LeFevre
2026-06-24 18:07:01 +00:00
committed by GitHub
parent d1daea9905
commit 4f19256298
7 changed files with 60 additions and 14 deletions
+3 -3
View File
@@ -114,12 +114,12 @@ int BPF_PROG(security_file_open, struct file *f)
return 0; 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, // 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 // security_file_open will not be called so we fall back to using the
// unresolved path in the emitted event. // unresolved path in the emitted event.
SEC("fexit/do_filp_open") SEC("fexit/do_file_open")
int BPF_PROG(do_filp_open_exit, int dfd, struct filename *pathname, const struct open_flags *op, struct file *ret) 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(); struct task_struct *task = bpf_get_current_task_btf();
u32 session_id = task->sessionid; u32 session_id = task->sessionid;
+50 -3
View File
@@ -22,10 +22,12 @@ package bpf
import ( import (
"context" "context"
"errors"
"io" "io"
"sync" "sync"
"github.com/cilium/ebpf" "github.com/cilium/ebpf"
"github.com/cilium/ebpf/btf"
"github.com/cilium/ebpf/link" "github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/ringbuf" "github.com/cilium/ebpf/ringbuf"
"github.com/cilium/ebpf/rlimit" "github.com/cilium/ebpf/rlimit"
@@ -36,6 +38,11 @@ import (
"github.com/gravitational/teleport/lib/observability/metrics" "github.com/gravitational/teleport/lib/observability/metrics"
) )
const (
doFilpOpenName = "do_filp_open"
doFileOpenName = "do_file_open"
)
var lostDiskEvents = prometheus.NewCounter( var lostDiskEvents = prometheus.NewCounter(
prometheus.CounterOpts{ prometheus.CounterOpts{
Name: teleport.MetricLostDiskEvents, Name: teleport.MetricLostDiskEvents,
@@ -71,9 +78,28 @@ func startOpen(bufferSize int) (*open, error) {
return nil, trace.Wrap(err) 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 var objs diskObjects
if err := loadDiskObjects(&objs, nil); err != nil { spec, err := loadDisk()
return nil, trace.Wrap(err, "loading disk objects: %v", err) 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) lostCtr, err := NewCounter(objs.LostCounter, objs.LostDoorbell, lostDiskEvents)
@@ -91,7 +117,7 @@ func startOpen(bufferSize int) (*open, error) {
attachType: ebpf.AttachTraceFEntry, attachType: ebpf.AttachTraceFEntry,
}, },
{ {
prog: objs.DoFilpOpenExit, prog: objs.DoFileOpenExit,
attachType: ebpf.AttachTraceFExit, attachType: ebpf.AttachTraceFExit,
}, },
} }
@@ -124,6 +150,27 @@ func startOpen(bufferSize int) (*open, error) {
return o, nil 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 { func (o *open) startSession(auditSessionID uint32) error {
o.mtx.Lock() o.mtx.Lock()
defer o.mtx.Unlock() defer o.mtx.Unlock()
+3 -3
View File
@@ -67,7 +67,7 @@ type diskSpecs struct {
// //
// It can be passed ebpf.CollectionSpec.Assign. // It can be passed ebpf.CollectionSpec.Assign.
type diskProgramSpecs struct { 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"` SecurityFileOpen *ebpf.ProgramSpec `ebpf:"security_file_open"`
} }
@@ -137,13 +137,13 @@ type diskVariables struct {
// //
// It can be passed to loadDiskObjects or ebpf.CollectionSpec.LoadAndAssign. // It can be passed to loadDiskObjects or ebpf.CollectionSpec.LoadAndAssign.
type diskPrograms struct { 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"` SecurityFileOpen *ebpf.Program `ebpf:"security_file_open"`
} }
func (p *diskPrograms) Close() error { func (p *diskPrograms) Close() error {
return _DiskClose( return _DiskClose(
p.DoFilpOpenExit, p.DoFileOpenExit,
p.SecurityFileOpen, p.SecurityFileOpen,
) )
} }
Binary file not shown.
+3 -3
View File
@@ -67,7 +67,7 @@ type diskSpecs struct {
// //
// It can be passed ebpf.CollectionSpec.Assign. // It can be passed ebpf.CollectionSpec.Assign.
type diskProgramSpecs struct { 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"` SecurityFileOpen *ebpf.ProgramSpec `ebpf:"security_file_open"`
} }
@@ -137,13 +137,13 @@ type diskVariables struct {
// //
// It can be passed to loadDiskObjects or ebpf.CollectionSpec.LoadAndAssign. // It can be passed to loadDiskObjects or ebpf.CollectionSpec.LoadAndAssign.
type diskPrograms struct { 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"` SecurityFileOpen *ebpf.Program `ebpf:"security_file_open"`
} }
func (p *diskPrograms) Close() error { func (p *diskPrograms) Close() error {
return _DiskClose( return _DiskClose(
p.DoFilpOpenExit, p.DoFileOpenExit,
p.SecurityFileOpen, p.SecurityFileOpen,
) )
} }
Binary file not shown.
+1 -2
View File
@@ -1343,7 +1343,6 @@ func runCommand(t *testing.T, srv Server, bpfSrv bpf.BPF, command string, expect
scx.execRequest.SetCommand(command) scx.execRequest.SetCommand(command)
clientChan, serverChan := newMockSSHChannel(t) clientChan, serverChan := newMockSSHChannel(t)
clientChan.Drain()
t.Logf("running %q", command) 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) stdout := make([]byte, 1024)
for { for {
_, err := serverChan.Read(stdout) _, err := clientChan.Read(stdout)
if err != nil { if err != nil {
if errors.Is(err, io.EOF) { if errors.Is(err, io.EOF) {
return return