From 0ec0a73290df796bdb5e614d554163a59776c24d Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Fri, 18 Oct 2024 18:45:14 +0200 Subject: [PATCH] add bpf to ebpf --- go.mod | 1 + go.sum | 2 + pkg/security/ebpf/probes/tc.go | 74 +++++++++++++++++++++++++++++----- 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 9b4978e72091df..1c53fb0909d05c 100644 --- a/go.mod +++ b/go.mod @@ -603,6 +603,7 @@ require ( github.com/DataDog/datadog-agent/pkg/config/structure v0.60.0-devel github.com/DataDog/datadog-agent/pkg/util/defaultpaths v0.0.0-00010101000000-000000000000 github.com/NVIDIA/go-nvml v0.12.4-0 + github.com/cloudflare/cbpfc v0.0.0-20240920015331-ff978e94500b github.com/containerd/containerd/api v1.7.19 github.com/containerd/errdefs v0.1.0 github.com/distribution/reference v0.6.0 diff --git a/go.sum b/go.sum index 08658fcc4533ce..2ee0edfc8697e1 100644 --- a/go.sum +++ b/go.sum @@ -1039,6 +1039,8 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cbpfc v0.0.0-20240920015331-ff978e94500b h1:EgR1t4Lnq6uP6QxJQ+oIFtENOHUY3/7gMOE76vL0KcA= +github.com/cloudflare/cbpfc v0.0.0-20240920015331-ff978e94500b/go.mod h1:X/9cHz8JVzKlvoZyKBgMgrogKZlLf+pWjmm5gSUm5dI= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cloudfoundry-community/go-cfclient/v2 v2.0.1-0.20230503155151-3d15366c5820 h1:ixkQUDJYG6eSxgUEl6LLE2l2TD2C5AYmlm+fVhsr6Zs= diff --git a/pkg/security/ebpf/probes/tc.go b/pkg/security/ebpf/probes/tc.go index 9287ab87ce35fa..7e2108b3233b68 100644 --- a/pkg/security/ebpf/probes/tc.go +++ b/pkg/security/ebpf/probes/tc.go @@ -9,11 +9,13 @@ package probes import ( - "fmt" - manager "github.com/DataDog/ebpf-manager" "github.com/cilium/ebpf" "github.com/cilium/ebpf/asm" + "github.com/cloudflare/cbpfc" + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcap" + "golang.org/x/net/bpf" "golang.org/x/sys/unix" ) @@ -72,35 +74,85 @@ var RawPacketTCProgram = []string{ // GetRawPacketTCFilterProg returns a first tc filter func GetRawPacketTCFilterProg(rawPacketEventMapFd, clsRouterMapFd int) (*ebpf.ProgramSpec, error) { + pcapBPF, err := pcap.CompileBPFFilter(layers.LinkTypeEthernet, 256, "port 5555") + if err != nil { + return nil, err + } + bpfInsts := make([]bpf.Instruction, len(pcapBPF)) + for i, ri := range pcapBPF { + bpfInsts[i] = bpf.RawInstruction{Op: ri.Code, Jt: ri.Jt, Jf: ri.Jf, K: ri.K}.Disassemble() + } + const ( - ctxReg = asm.R9 - dataReg = asm.R6 + ctxReg = asm.R9 + + // raw packet data, see kernel definition + dataSize = 256 + dataOffset = 164 ) + opts := cbpfc.EBPFOpts{ + PacketStart: asm.R1, + PacketEnd: asm.R2, + Result: asm.R3, + Working: [4]asm.Register{ + asm.R4, + asm.R5, + asm.R6, + asm.R7, + }, + LabelPrefix: "cbpfc-", + ResultLabel: "result", + StackOffset: 16, // adapt using the stack used outside of the filter itself, ex: map_lookup + } + + filterInsts, err := cbpfc.ToEBPF(bpfInsts, opts) + if err != nil { + return nil, err + } + insts := asm.Instructions{ // save ctx asm.Mov.Reg(ctxReg, asm.R1), + } + insts = append(insts, + // save ctx + asm.Mov.Reg(ctxReg, asm.R1), // load raw event asm.Mov.Reg(asm.R2, asm.RFP), asm.Add.Imm(asm.R2, -4), - asm.StoreImm(asm.R2, 0, 0, asm.Word), + asm.StoreImm(asm.R2, 0, 0, asm.Word), // index 0 asm.LoadMapPtr(asm.R1, rawPacketEventMapFd), asm.FnMapLookupElem.Call(), asm.JNE.Imm(asm.R0, 0, "raw-packet-event-not-null"), asm.Return(), - asm.Mov.Reg(dataReg, asm.R0).WithSymbol("raw-packet-event-not-null"), - // jump to the send event program - asm.Mov.Reg(asm.R1, ctxReg), + // place in result in the start register and end register + asm.Mov.Reg(opts.PacketStart, asm.R0).WithSymbol("raw-packet-event-not-null"), + asm.Add.Imm(opts.PacketStart, dataOffset), + asm.Mov.Reg(opts.PacketEnd, opts.PacketStart), + asm.Add.Imm(opts.PacketEnd, dataSize), + ) + + // insert the filter + insts = append(insts, filterInsts...) + + // filter output + insts = append(insts, + asm.JNE.Imm(opts.Result, 0, "send-event").WithSymbol(opts.ResultLabel), + asm.Return(), + ) + + // tail call to the send event program + insts = append(insts, + asm.Mov.Reg(asm.R1, ctxReg).WithSymbol("send-event"), asm.LoadMapPtr(asm.R2, clsRouterMapFd), asm.Mov.Imm(asm.R3, int32(TCRawPacketParserKey)), asm.FnTailCall.Call(), asm.Mov.Imm(asm.R0, 0), asm.Return(), - } - - fmt.Printf("INS: %+v\n", insts) + ) return &ebpf.ProgramSpec{ Type: ebpf.SchedCLS,