Skip to content

Commit ce913f7

Browse files
committed
Support ARCH_X86_64 in asm
1 parent 9e42506 commit ce913f7

7 files changed

Lines changed: 50 additions & 30 deletions

File tree

.codeclimate.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ plugins:
66
exclude_paths:
77
- spec/
88
checks:
9-
method-lines:
9+
file-lines:
1010
enabled: false
1111
method-count:
1212
enabled: false
13+
method-complexity:
14+
enabled: false
1315
exclude_patterns:
1416
- spec/

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ $ seccomp-tools asm
167167
$ cat spec/data/libseccomp.asm
168168
# # check if arch is X86_64
169169
# A = arch
170-
# A == 0xc000003e ? next : dead
170+
# A == ARCH_X86_64 ? next : dead
171171
# A = sys_number
172172
# A >= 0x40000000 ? dead : next
173173
# A == write ? ok : next

lib/seccomp-tools/asm/compiler.rb

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ def process(line)
4242
else
4343
@insts << res
4444
end
45-
res
4645
end
4746

4847
# @return [Array<SeccompTools::BPF>]
@@ -84,11 +83,10 @@ def emit(*args, k: 0, jt: 0, jf: 0)
8483
# mem[i] = <A|X>
8584
def compile_assign(dst, src)
8685
# misc txa / tax
87-
return emit(:misc, :txa) if dst == :a && src == :x
88-
return emit(:misc, :tax) if dst == :x && src == :a
89-
src = evaluate(src)
86+
return compile_assign_misc(dst, src) if (dst == :a && src == :x) || (dst == :x && src == :a)
9087
# case of st / stx
91-
return emit(src == :x ? :stx : :st, k: dst.last) if dst[0] == :mem
88+
return emit(src == :x ? :stx : :st, k: dst.last) if dst.is_a?(Array) && dst.first == :mem
89+
src = evaluate(src)
9290
ld = dst == :x ? :ldx : :ld
9391
# <A|X> = <immi>
9492
return emit(ld, :imm, k: src) if src.is_a?(Integer)
@@ -99,6 +97,10 @@ def compile_assign(dst, src)
9997
emit(ld, :abs, k: src.last)
10098
end
10199

100+
def compile_assign_misc(dst, _src)
101+
emit(:misc, dst == :a ? :txa : :tax)
102+
end
103+
102104
def compile_alu(op, val)
103105
val = evaluate(val)
104106
src = val == :x ? :x : :k
@@ -138,13 +140,17 @@ def evaluate(val)
138140
when 'arch' then [:data, 4]
139141
else val
140142
end
141-
return Const::Syscall.const_get(@arch.upcase.to_sym)[val.to_sym] if val.is_a?(String)
143+
return eval_constants(val) if val.is_a?(String)
142144
# remains are [:mem/:data/:args, <num>]
143145
# first convert args to data
144146
val = [:data, val.last * 8 + 16] if val.first == :args
145147
val
146148
end
147149

150+
def eval_constants(str)
151+
Const::Syscall.const_get(@arch.upcase.to_sym)[str.to_sym] || Const::Audit::ARCH[str]
152+
end
153+
148154
attr_reader :token
149155

150156
# A <comparison> <sys_str|X|Integer> ? <label|Integer> : <label|Integer>

lib/seccomp-tools/asm/tokenizer.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def fetch!(type)
4040
res = case type
4141
when String then fetch_str(type) || raise_expected("token #{type.inspect}")
4242
when :comparison then fetch_strs(COMPARISON).to_sym || raise_expected('a comparison operator')
43-
when :sys_num_x then fetch_sys_num_x || raise_expected("a syscall number or 'X'")
43+
when :sys_num_x then fetch_sys_num_arch_x || raise_expected("a syscall number or 'X'")
4444
when :goto then fetch_number || fetch_label || raise_expected('a number or label name')
4545
when :ret then fetch_return || raise(ArgumentError, <<-EOS)
4646
Invalid return type: #{cur.inspect}.
@@ -74,9 +74,9 @@ def fetch_ax
7474
nil
7575
end
7676

77-
def fetch_sys_num_x
77+
def fetch_sys_num_arch_x
7878
return :x if fetch_str('X')
79-
fetch_number || fetch_syscall
79+
fetch_number || fetch_syscall || fetch_arch
8080
end
8181

8282
# Currently only supports 10-based decimal numbers.
@@ -92,6 +92,10 @@ def fetch_syscall
9292
fetch_strs(sys.keys.map(&:to_s).sort_by(&:size).reverse)
9393
end
9494

95+
def fetch_arch
96+
fetch_strs(Const::Audit::ARCH.keys)
97+
end
98+
9599
def fetch_regexp(regexp)
96100
idx = cur =~ regexp
97101
return nil if idx.nil? || idx != 0

lib/seccomp-tools/cli/emu.rb

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ def handle
4444
return CLI.show(parser.help) if option[:ifile].nil?
4545
raw = input
4646
insts = SeccompTools::Disasm.to_bpf(raw, option[:arch]).map(&:inst)
47-
disasm = SeccompTools::Disasm.disasm(raw, arch: option[:arch])
4847
sys, *args = argv
4948
sys = Integer(sys) if sys
5049
args.map! { |v| Integer(v) }
@@ -54,26 +53,36 @@ def handle
5453
end
5554

5655
if option[:verbose] >= 1
57-
disasm = disasm.lines
58-
output { disasm.shift }
59-
output { disasm.shift }
60-
disasm.each_with_index do |line, idx|
61-
output do
62-
next line if trace.member?(idx)
63-
Util.colorize(line, t: :gray)
64-
end
65-
# Too much remain, omit them.
66-
rem = disasm.size - idx - 1
67-
break output { Util.colorize("... (omitting #{rem} lines)\n", t: :gray) } if rem > 3 && idx > res[:pc] + 4
68-
end
69-
output { "\n" }
56+
disasm = SeccompTools::Disasm.disasm(raw, arch: option[:arch]).lines
57+
output_emulate_path(disasm, trace, res)
7058
end
7159
output do
7260
ret_type = Const::BPF::ACTION.invert[res[:ret] & 0x7fff0000]
7361
errno = ret_type == :ERRNO ? "(#{res[:ret] & 0xffff})" : ''
7462
format("return %s%s at line %04d\n", ret_type, errno, res[:pc])
7563
end
7664
end
65+
66+
private
67+
68+
# output the path during emulation
69+
# @param [Array<String>] disasm
70+
# @param [Set] trace
71+
# @param [{Symbol => Object}] result
72+
def output_emulate_path(disasm, trace, result)
73+
output { disasm.shift }
74+
output { disasm.shift }
75+
disasm.each_with_index do |line, idx|
76+
output do
77+
next line if trace.member?(idx)
78+
Util.colorize(line, t: :gray)
79+
end
80+
# Too much remain, omit them.
81+
rem = disasm.size - idx - 1
82+
break output { Util.colorize("... (omitting #{rem} lines)\n", t: :gray) } if rem > 3 && idx > result[:pc] + 4
83+
end
84+
output { "\n" }
85+
end
7786
end
7887
end
7988
end

lib/seccomp-tools/instruction/jmp.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@ class JMP < Base
99
def decompile
1010
return goto(k) if jop == :none
1111
# if jt == 0 && jf == 0 => no-op # should not happen
12-
# jt == 0 => if(!) goto jf
12+
# jt == 0 => if(!) goto jf;
1313
# jf == 0 => if() goto jt;
1414
# otherwise => if () goto jt; else goto jf;
1515
return '/* no-op */' if jt.zero? && jf.zero?
1616
return goto(jt) if jt == jf
17-
return if_str + goto(jt) + ' else ' + goto(jf) unless jt.zero? || jf.zero?
18-
return if_str + goto(jt) if jf.zero?
19-
if_str(true) + goto(jf)
17+
return if_str(true) + goto(jf) if jt.zero?
18+
if_str + goto(jt) + (jf.zero? ? '' : ' else ' + goto(jf))
2019
end
2120

2221
# See {Instruction::Base#symbolize}.

spec/data/libseccomp.asm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# check if arch is X86_64
22
A = arch
3-
A == 0xc000003e ? next : dead
3+
A == ARCH_X86_64 ? next : dead
44
A = sys_number
55
A >= 0x40000000 ? dead : next
66
A == write ? ok : next

0 commit comments

Comments
 (0)