Class: SeccompTools::BPF

Inherits:
Object
  • Object
show all
Defined in:
lib/seccomp-tools/bpf.rb

Overview

One BPF instruction, i.e. a struct sock_filter.

Beyond the four fields of the C struct, a BPF also carries the architecture it belongs to and its line number, which together allow it to be disassembled into readable assembly.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw, arch, line) ⇒ BPF

Instantiate a SeccompTools::BPF object.

Parameters:

  • raw (String, {Symbol => Integer})

    One struct sock_filter, either as 8 raw bytes or as a hash of the :code, :jt, :jf and :k fields.

  • arch (Symbol)

    Architecture, for showing constant names in decompile.

  • line (Integer)

    Line number of this filter.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/seccomp-tools/bpf.rb', line 38

def initialize(raw, arch, line)
  if raw.is_a?(String)
    io = ::StringIO.new(raw)
    endian = Const::Endian::ENDIAN[arch]
    @code = io.read(2).unpack1("S#{endian}")
    @jt = io.read(1).ord
    @jf = io.read(1).ord
    @k = io.read(4).unpack1("L#{endian}")
  else
    @code = raw[:code]
    @jt = raw[:jt]
    @jf = raw[:jf]
    @k = raw[:k]
  end
  @arch = arch
  @line = line
  @states = Set.new
  @disasm_setting = {
    code: true,
    arg_infer: true
  }
end

Instance Attribute Details

#archSymbol (readonly)

Returns Architecture.

Returns:

  • (Symbol)

    Architecture.



26
27
28
# File 'lib/seccomp-tools/bpf.rb', line 26

def arch
  @arch
end

#codeInteger (readonly)

Returns BPF code.

Returns:

  • (Integer)

    BPF code.



18
19
20
# File 'lib/seccomp-tools/bpf.rb', line 18

def code
  @code
end

#jfInteger (readonly)

Returns BPF JF.

Returns:

  • (Integer)

    BPF JF.



22
23
24
# File 'lib/seccomp-tools/bpf.rb', line 22

def jf
  @jf
end

#jtInteger (readonly)

Returns BPF JT.

Returns:

  • (Integer)

    BPF JT.



20
21
22
# File 'lib/seccomp-tools/bpf.rb', line 20

def jt
  @jt
end

#kInteger (readonly)

Returns BPF K.

Returns:

  • (Integer)

    BPF K.



24
25
26
# File 'lib/seccomp-tools/bpf.rb', line 24

def k
  @k
end

#lineInteger (readonly)

Returns Line number.

Returns:

  • (Integer)

    Line number.



16
17
18
# File 'lib/seccomp-tools/bpf.rb', line 16

def line
  @line
end

#statesSet<SeccompTools::Symbolic::State>

Returns Possible states before this instruction.

Returns:



28
29
30
# File 'lib/seccomp-tools/bpf.rb', line 28

def states
  @states
end

Instance Method Details

#asmString

Convert to raw bytes.

Returns:

  • (String)

    Raw bpf bytes.



94
95
96
97
# File 'lib/seccomp-tools/bpf.rb', line 94

def asm
  endian = Const::Endian::ENDIAN[arch]
  [code, jt, jf, k].pack("S#{endian}CCL#{endian}")
end

#branch(state) {|pc, st| ... } ⇒ void

This method returns an undefined value.

Yields every branch that may be taken after executing this instruction.

Parameters:

Yield Parameters:



121
122
123
# File 'lib/seccomp-tools/bpf.rb', line 121

def branch(state, &)
  inst.branch(state).each(&)
end

#commandSymbol?

Command according to code.

Returns:



102
103
104
# File 'lib/seccomp-tools/bpf.rb', line 102

def command
  Const::BPF::COMMAND.invert[code & 7]
end

#decompileString

Decompile.

Returns:

  • (String)

    Decompile string.



109
110
111
# File 'lib/seccomp-tools/bpf.rb', line 109

def decompile
  inst.decompile
end

#disasm(**options) ⇒ String

Pretty display the disassemble result.

Parameters:

  • options ({Symbol => Boolean})

    Display settings, merged into the current ones. Supports :code, whether to show the raw code, jt, jf and k fields, and :arg_infer, whether to annotate the line with the inferred syscall argument.

Returns:

  • (String)

    One line of disassembly, without a trailing newline.



68
69
70
71
72
73
74
75
76
77
# File 'lib/seccomp-tools/bpf.rb', line 68

def disasm(**options)
  @disasm_setting.merge!(options)
  if show_code?
    format(' %04d: 0x%02x 0x%02x 0x%02x 0x%08x  %s',
           line, code, jt, jf, k, decompile)
  else
    format('%04d: %s',
           line, decompile)
  end
end

#instSeccompTools::Instruction::Base

Corresponding instruction object.



127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/seccomp-tools/bpf.rb', line 127

def inst
  @inst ||= case command
            when :alu  then SeccompTools::Instruction::ALU
            when :jmp  then SeccompTools::Instruction::JMP
            when :ld   then SeccompTools::Instruction::LD
            when :ldx  then SeccompTools::Instruction::LDX
            when :misc then SeccompTools::Instruction::MISC
            when :ret  then SeccompTools::Instruction::RET
            when :st   then SeccompTools::Instruction::ST
            when :stx  then SeccompTools::Instruction::STX
            end.new(self)
end

#show_arg_infer?Boolean

Whether the syscall argument names need to be inferred.

Returns:

  • (Boolean)


87
88
89
# File 'lib/seccomp-tools/bpf.rb', line 87

def show_arg_infer?
  @disasm_setting[:arg_infer]
end

#show_code?Boolean

Whether the raw code, jt, jf, k fields need to be dumped.

Returns:

  • (Boolean)


81
82
83
# File 'lib/seccomp-tools/bpf.rb', line 81

def show_code?
  @disasm_setting[:code]
end