Documentation ¶
Overview ¶
Package bpf provides tools for working with Berkeley Packet Filter (BPF) programs. More information on BPF can be found at https://www.freebsd.org/cgi/man.cgi?bpf(4)
Index ¶
- Constants
- func Decode(ins Instruction) (string, error)
- func DecodeInstructions(instns []Instruction) (string, error)
- func DecodeProgram(p Program) (string, error)
- func Exec[endian Endianness](p Program, in Input) (uint32, error)
- func ToBytecode(insns []Instruction) []byte
- type BigEndian
- type Endianness
- type Error
- type ExecutionMetrics
- type FragmentOutcomes
- type Input
- type Instruction
- func (ins Instruction) Equal(other Instruction) bool
- func (ins Instruction) IsConditionalJump() bool
- func (ins Instruction) IsJump() bool
- func (ins Instruction) IsReturn() bool
- func (ins Instruction) IsUnconditionalJump() bool
- func (ins Instruction) JumpOffsets() []JumpOffset
- func (ins Instruction) ModifiesRegisterA() bool
- func (ins *Instruction) StateFields() []string
- func (ins *Instruction) StateLoad(ctx context.Context, stateSourceObject state.Source)
- func (ins *Instruction) StateSave(stateSinkObject state.Sink)
- func (ins *Instruction) StateTypeName() string
- func (ins *Instruction) String() string
- type JumpOffset
- type JumpType
- type LittleEndian
- type NativeEndian
- type Program
- type ProgramBuilder
- func (b *ProgramBuilder) AddDirectJumpLabel(labelName string)
- func (b *ProgramBuilder) AddJump(code uint16, k uint32, jt, jf uint8)
- func (b *ProgramBuilder) AddJumpFalseLabel(code uint16, k uint32, jt uint8, jfLabel string)
- func (b *ProgramBuilder) AddJumpLabels(code uint16, k uint32, jtLabel, jfLabel string)
- func (b *ProgramBuilder) AddJumpTrueLabel(code uint16, k uint32, jtLabel string, jf uint8)
- func (b *ProgramBuilder) AddLabel(name string) error
- func (b *ProgramBuilder) AddStmt(code uint16, k uint32)
- func (b *ProgramBuilder) Instructions() ([]Instruction, error)
- func (b *ProgramBuilder) Record() func() ProgramFragment
- type ProgramFragment
Constants ¶
const ( // MaxInstructions is the maximum number of instructions in a BPF program, // and is equal to Linux's BPF_MAXINSNS. MaxInstructions = 4096 // ScratchMemRegisters is the number of M registers in a BPF virtual machine, // and is equal to Linux's BPF_MEMWORDS. ScratchMemRegisters = 16 )
const ( // Instruction class, stored in bits 0-2. Ld = 0x00 // load into A Ldx = 0x01 // load into X St = 0x02 // store from A Stx = 0x03 // store from X Alu = 0x04 // arithmetic Jmp = 0x05 // jump Ret = 0x06 // return Misc = 0x07 // Size of a load, stored in bits 3-4. W = 0x00 // 32 bits H = 0x08 // 16 bits B = 0x10 // 8 bits // Source operand for a load, stored in bits 5-7. // Address mode numbers in the comments come from Linux's // Documentation/networking/filter.txt. Imm = 0x00 // immediate value K (mode 4) Abs = 0x20 // data in input at byte offset K (mode 1) Ind = 0x40 // data in input at byte offset X+K (mode 2) Mem = 0x60 // M[K] (mode 3) Len = 0x80 // length of the input in bytes ("BPF extension len") Msh = 0xa0 // 4 * lower nibble of input at byte offset K (mode 5) // Source operands for arithmetic, jump, and return instructions. // Arithmetic and jump instructions can use K or X as source operands. // Return instructions can use K or A as source operands. K = 0x00 // still mode 4 X = 0x08 // mode 0 A = 0x10 // mode 9 // Arithmetic instructions, stored in bits 4-7. Add = 0x00 Sub = 0x10 // A - src Mul = 0x20 Div = 0x30 // A / src Or = 0x40 And = 0x50 Lsh = 0x60 // A << src Rsh = 0x70 // A >> src Neg = 0x80 // -A (src ignored) Mod = 0x90 // A % src Xor = 0xa0 // Jump instructions, stored in bits 4-7. Ja = 0x00 // unconditional (uses K for jump offset) Jeq = 0x10 // if A == src Jgt = 0x20 // if A > src Jge = 0x30 // if A >= src Jset = 0x40 // if (A & src) != 0 // Miscellaneous instructions, stored in bits 3-7. Tax = 0x00 // A = X Txa = 0x80 // X = A )
Parts of a linux.BPFInstruction.OpCode. Compare to the Linux kernel's include/uapi/linux/filter.h.
In the comments below:
A, X, and M[] are BPF virtual machine registers.
K refers to the instruction field linux.BPFInstruction.K.
Bits are counted from the LSB position.
const ( // DivisionByZero indicates that a program contains, or executed, a // division or modulo by zero. DivisionByZero = iota // InvalidEndOfProgram indicates that the last instruction of a program is // not a return. InvalidEndOfProgram // InvalidInstructionCount indicates that a program has zero instructions // or more than MaxInstructions instructions. InvalidInstructionCount // InvalidJumpTarget indicates that a program contains a jump whose target // is outside of the program's bounds. InvalidJumpTarget // InvalidLoad indicates that a program executed an invalid load of input // data. InvalidLoad // InvalidOpcode indicates that a program contains an instruction with an // invalid opcode. InvalidOpcode // InvalidRegister indicates that a program contains a load from, or store // to, a non-existent M register (index >= ScratchMemRegisters). InvalidRegister )
Possible values for ProgramError.Code.
Variables ¶
This section is empty.
Functions ¶
func Decode ¶
func Decode(ins Instruction) (string, error)
Decode translates a single BPF instruction into text format.
func DecodeInstructions ¶
func DecodeInstructions(instns []Instruction) (string, error)
DecodeInstructions translates an array of BPF instructions into text format.
func DecodeProgram ¶
DecodeProgram translates a compiled BPF program into text format.
func Exec ¶
func Exec[endian Endianness](p Program, in Input) (uint32, error)
Exec executes a BPF program over the given input and returns its return value.
func ToBytecode ¶
func ToBytecode(insns []Instruction) []byte
ToBytecode converts BPF instructions into raw BPF bytecode.
Types ¶
type Endianness ¶
type Endianness interface { BigEndian | LittleEndian | NativeEndian }
Endianness represents a byte order.
type Error ¶
type Error struct { // Code indicates the kind of error that occurred. Code int // PC is the program counter (index into the list of instructions) at which // the error occurred. PC int }
Error is an error encountered while compiling or executing a BPF program.
type ExecutionMetrics ¶
type ExecutionMetrics struct { // ReturnValue is the result of the program execution. ReturnValue uint32 // Coverage maps instruction indexes to whether or not they were executed. // This slice has the same size as the number of instructions as the BPF // program that was run, so it can be used as a way to get the program size. // Since an instruction can never run twice in BPF, this can also be used // to determine how many instructions were executed. Coverage []bool // InputAccessed maps input byte offsets to whether or not they were // read by the program during execution. InputAccessed []bool }
ExecutionMetrics represents the result of executing a BPF program.
func InstrumentedExec ¶
func InstrumentedExec[endian Endianness](p Program, in Input) (ExecutionMetrics, error)
InstrumentedExec executes a BPF program over the given input while instrumenting it: recording memory accesses and lines executed. This is slower than Exec, but should return equivalent results.
func (*ExecutionMetrics) String ¶
func (e *ExecutionMetrics) String() string
String returns a human-readable view of an `Execution`.
type FragmentOutcomes ¶
type FragmentOutcomes struct { // MayFallThrough is true if executing the fragment may cause it to start // executing the program instruction that comes right after the last // instruction in this fragment (i.e. at `Fragment.toPC`). MayFallThrough bool // MayJumpToKnownOffsetBeyondFragment is true if executing the fragment may // jump to a fixed offset (or resolved label) that is not within the range // of the fragment itself, nor does it point to the instruction that would // come right after this fragment. // If the fragment jumps to an unresolved label, this will instead be // indicated in `MayJumpToUnresolvedLabels`. MayJumpToKnownOffsetBeyondFragment bool // MayJumpToUnresolvedLabels is the set of named labels that have not yet // been added to the program (the labels are not resolvable) but that the // fragment may jump to. MayJumpToUnresolvedLabels map[string]struct{} // MayReturnImmediate contains the set of possible immediate return values // that the fragment may return. MayReturnImmediate map[linux.BPFAction]struct{} // MayReturnRegisterA is true if the fragment may return the value of // register A. MayReturnRegisterA bool }
FragmentOutcomes represents the set of outcomes that a ProgramFragment execution may result into.
func (FragmentOutcomes) MayReturn ¶
func (o FragmentOutcomes) MayReturn() bool
MayReturn returns whether the fragment may return for any reason.
func (FragmentOutcomes) String ¶
func (o FragmentOutcomes) String() string
String returns a list of possible human-readable outcomes.
type Input ¶
type Input []byte
Input represents a source of input data for a BPF program. (BPF documentation sometimes refers to the input data as the "packet" due to its origins as a packet processing DSL.) Unaligned loads are supported.
type Instruction ¶
type Instruction linux.BPFInstruction
Instruction is a type alias for linux.BPFInstruction. It adds a human-readable stringification and other helper functions.
+marshal slice:InstructionSlice +stateify savable +stateify identtype
func Jump ¶
func Jump(code uint16, k uint32, jt, jf uint8) Instruction
Jump returns an Instruction representing a BPF jump instruction.
func Optimize ¶
func Optimize(insns []Instruction) []Instruction
Optimize losslessly optimizes a BPF program. The BPF instructions are assumed to have been checked for validity and consistency. The instructions in `insns` may be modified in-place.
func ParseBytecode ¶
func ParseBytecode(bytecode []byte) ([]Instruction, error)
ParseBytecode converts raw BPF bytecode into BPF instructions. It verifies that the resulting set of instructions is a valid program.
func Stmt ¶
func Stmt(code uint16, k uint32) Instruction
Stmt returns an Instruction representing a BPF non-jump instruction.
func (Instruction) Equal ¶
func (ins Instruction) Equal(other Instruction) bool
Equal returns whether this instruction is equivalent to `other`.
func (Instruction) IsConditionalJump ¶
func (ins Instruction) IsConditionalJump() bool
IsConditionalJump returns true if `ins` is a conditional jump instruction.
func (Instruction) IsJump ¶
func (ins Instruction) IsJump() bool
IsJump returns true if `ins` is a jump instruction.
func (Instruction) IsReturn ¶
func (ins Instruction) IsReturn() bool
IsReturn returns true if `ins` is a return instruction.
func (Instruction) IsUnconditionalJump ¶
func (ins Instruction) IsUnconditionalJump() bool
IsUnconditionalJump returns true if `ins` is a conditional jump instruction.
func (Instruction) JumpOffsets ¶
func (ins Instruction) JumpOffsets() []JumpOffset
JumpOffsets returns the set of instruction offsets that this instruction may jump to. Returns a nil slice if this is not a jump instruction.
func (Instruction) ModifiesRegisterA ¶
func (ins Instruction) ModifiesRegisterA() bool
ModifiesRegisterA returns true iff this instruction modifies the value of the "A" register.
func (*Instruction) StateFields ¶
func (ins *Instruction) StateFields() []string
func (*Instruction) StateLoad ¶
func (ins *Instruction) StateLoad(ctx context.Context, stateSourceObject state.Source)
+checklocksignore
func (*Instruction) StateSave ¶
func (ins *Instruction) StateSave(stateSinkObject state.Sink)
+checklocksignore
func (*Instruction) StateTypeName ¶
func (ins *Instruction) StateTypeName() string
func (*Instruction) String ¶
func (ins *Instruction) String() string
String returns a human-readable version of the instruction.
type JumpOffset ¶
type JumpOffset struct { // Type is the type of jump that an instruction may execute. Type JumpType // Offset is the number of instructions that the jump skips over. Offset uint32 }
JumpOffset is a possible jump offset that an instruction may jump to.
type Program ¶
type Program struct {
// contains filtered or unexported fields
}
Program is a BPF program that has been validated for consistency.
+stateify savable
func Compile ¶
func Compile(insns []Instruction, optimize bool) (Program, error)
Compile performs validation and optimization on a sequence of BPF instructions before wrapping them in a Program.
func (*Program) StateFields ¶
func (*Program) StateTypeName ¶
type ProgramBuilder ¶
type ProgramBuilder struct {
// contains filtered or unexported fields
}
ProgramBuilder assists with building a BPF program with jump labels that are resolved to their proper offsets.
func NewProgramBuilder ¶
func NewProgramBuilder() *ProgramBuilder
NewProgramBuilder creates a new ProgramBuilder instance.
func (*ProgramBuilder) AddDirectJumpLabel ¶
func (b *ProgramBuilder) AddDirectJumpLabel(labelName string)
AddDirectJumpLabel adds a new jump to the program where is labelled.
func (*ProgramBuilder) AddJump ¶
func (b *ProgramBuilder) AddJump(code uint16, k uint32, jt, jf uint8)
AddJump adds a new jump to the program.
func (*ProgramBuilder) AddJumpFalseLabel ¶
func (b *ProgramBuilder) AddJumpFalseLabel(code uint16, k uint32, jt uint8, jfLabel string)
AddJumpFalseLabel adds a new jump to the program where 'jump if false' is a label.
func (*ProgramBuilder) AddJumpLabels ¶
func (b *ProgramBuilder) AddJumpLabels(code uint16, k uint32, jtLabel, jfLabel string)
AddJumpLabels adds a new jump to the program where both jump targets are labels.
func (*ProgramBuilder) AddJumpTrueLabel ¶
func (b *ProgramBuilder) AddJumpTrueLabel(code uint16, k uint32, jtLabel string, jf uint8)
AddJumpTrueLabel adds a new jump to the program where 'jump if true' is a label.
func (*ProgramBuilder) AddLabel ¶
func (b *ProgramBuilder) AddLabel(name string) error
AddLabel sets the given label name at the current location. The next instruction is executed when the any code jumps to this label. More than one label can be added to the same location.
func (*ProgramBuilder) AddStmt ¶
func (b *ProgramBuilder) AddStmt(code uint16, k uint32)
AddStmt adds a new statement to the program.
func (*ProgramBuilder) Instructions ¶
func (b *ProgramBuilder) Instructions() ([]Instruction, error)
Instructions returns an array of BPF instructions representing the program with all labels resolved. Return error in case label resolution failed due to an invalid program.
N.B. Partial results will be returned in the error case, which is useful for debugging.
func (*ProgramBuilder) Record ¶
func (b *ProgramBuilder) Record() func() ProgramFragment
Record starts recording the instructions being added to the ProgramBuilder until the returned function is called. The returned function returns a ProgramFragment which represents the recorded instructions. It may be called repeatedly.
type ProgramFragment ¶
type ProgramFragment struct {
// contains filtered or unexported fields
}
ProgramFragment is a set of not-compiled instructions that were added to a ProgramBuilder from the moment the `Record` function was called on it.
func (ProgramFragment) MayModifyRegisterA ¶
func (f ProgramFragment) MayModifyRegisterA() bool
MayModifyRegisterA returns whether this fragment may modify register A. A value of "true" does not necessarily mean that A *will* be modified, as the control flow of this fragment may skip over instructions that modify the A register.
func (ProgramFragment) Outcomes ¶
func (f ProgramFragment) Outcomes() FragmentOutcomes
Outcomes returns the set of possible outcomes that executing this fragment may result into.
func (ProgramFragment) String ¶
func (f ProgramFragment) String() string
String returns a string version of the fragment.