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 14:07:01 -04: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;
}
// 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;
+50 -3
View File
@@ -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()
+3 -3
View File
@@ -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,
)
}
Binary file not shown.
+3 -3
View File
@@ -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,
)
}
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)
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