seccomp-tools 1.1.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +112 -30
- data/bin/seccomp-tools +1 -0
- data/ext/ptrace/extconf.rb +2 -0
- data/ext/ptrace/ptrace.c +107 -5
- data/lib/seccomp-tools.rb +5 -0
- data/lib/seccomp-tools/asm/asm.rb +5 -2
- data/lib/seccomp-tools/asm/compiler.rb +96 -18
- data/lib/seccomp-tools/asm/tokenizer.rb +25 -8
- data/lib/seccomp-tools/bpf.rb +7 -4
- data/lib/seccomp-tools/cli/asm.rb +16 -6
- data/lib/seccomp-tools/cli/base.rb +10 -4
- data/lib/seccomp-tools/cli/cli.rb +9 -6
- data/lib/seccomp-tools/cli/disasm.rb +6 -2
- data/lib/seccomp-tools/cli/dump.rb +37 -6
- data/lib/seccomp-tools/cli/emu.rb +41 -22
- data/lib/seccomp-tools/const.rb +47 -16
- data/lib/seccomp-tools/consts/sys_arg.rb +432 -0
- data/lib/seccomp-tools/consts/sys_nr/aarch64.rb +284 -0
- data/lib/seccomp-tools/consts/{amd64.rb → sys_nr/amd64.rb} +6 -1
- data/lib/seccomp-tools/consts/{i386.rb → sys_nr/i386.rb} +18 -15
- data/lib/seccomp-tools/disasm/context.rb +125 -34
- data/lib/seccomp-tools/disasm/disasm.rb +5 -2
- data/lib/seccomp-tools/dumper.rb +75 -8
- data/lib/seccomp-tools/emulator.rb +19 -8
- data/lib/seccomp-tools/instruction/alu.rb +7 -2
- data/lib/seccomp-tools/instruction/base.rb +5 -3
- data/lib/seccomp-tools/instruction/instruction.rb +2 -0
- data/lib/seccomp-tools/instruction/jmp.rb +28 -14
- data/lib/seccomp-tools/instruction/ld.rb +28 -12
- data/lib/seccomp-tools/instruction/ldx.rb +2 -0
- data/lib/seccomp-tools/instruction/misc.rb +2 -0
- data/lib/seccomp-tools/instruction/ret.rb +14 -2
- data/lib/seccomp-tools/instruction/st.rb +4 -2
- data/lib/seccomp-tools/instruction/stx.rb +2 -0
- data/lib/seccomp-tools/logger.rb +40 -0
- data/lib/seccomp-tools/syscall.rb +24 -13
- data/lib/seccomp-tools/templates/asm.amd64.asm +26 -0
- data/lib/seccomp-tools/templates/asm.c +17 -0
- data/lib/seccomp-tools/templates/asm.i386.asm +33 -0
- data/lib/seccomp-tools/util.rb +24 -3
- data/lib/seccomp-tools/version.rb +3 -1
- metadata +51 -44
@@ -1,15 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'seccomp-tools/asm/tokenizer'
|
2
4
|
require 'seccomp-tools/bpf'
|
3
5
|
require 'seccomp-tools/const'
|
4
6
|
|
5
7
|
module SeccompTools
|
6
8
|
module Asm
|
9
|
+
# @private
|
10
|
+
#
|
7
11
|
# Compile seccomp rules.
|
8
12
|
class Compiler
|
13
|
+
# Instantiate a {Compiler} object.
|
14
|
+
#
|
15
|
+
# @param [Symbol] arch
|
16
|
+
# Architecture.
|
9
17
|
def initialize(arch)
|
10
18
|
@arch = arch
|
11
19
|
@insts = []
|
12
20
|
@labels = {}
|
21
|
+
@insts_linenum = {}
|
13
22
|
@input = []
|
14
23
|
end
|
15
24
|
|
@@ -24,13 +33,17 @@ module SeccompTools
|
|
24
33
|
line = remove_comment(line)
|
25
34
|
@token = Tokenizer.new(line)
|
26
35
|
return if line.empty?
|
36
|
+
|
27
37
|
begin
|
28
38
|
res = case line
|
29
39
|
when /\?/ then cmp
|
30
40
|
when /^#{Tokenizer::LABEL_REGEXP}:/ then define_label
|
31
41
|
when /^return/ then ret
|
42
|
+
when /^A\s*=\s*-A/ then alu_neg
|
32
43
|
when /^(A|X)\s*=[^=]/ then assign
|
33
|
-
when /^
|
44
|
+
when /^mem\[\d+\]\s*=\s*(A|X)/ then store
|
45
|
+
when /^A\s*.{1,2}=/ then alu
|
46
|
+
when /^(goto|jmp|jump)/ then jmp_abs
|
34
47
|
end
|
35
48
|
rescue ArgumentError => e
|
36
49
|
invalid(@input.size - 1, e.message)
|
@@ -40,11 +53,16 @@ module SeccompTools
|
|
40
53
|
@labels[res.last] = @insts.size
|
41
54
|
else
|
42
55
|
@insts << res
|
56
|
+
@insts_linenum[@insts.size - 1] = @input.size - 1
|
43
57
|
end
|
44
|
-
res
|
45
58
|
end
|
46
59
|
|
60
|
+
# Compiles the processed instructions.
|
61
|
+
#
|
47
62
|
# @return [Array<SeccompTools::BPF>]
|
63
|
+
# Returns the compiled {BPF} array.
|
64
|
+
# @raise [ArgumentError]
|
65
|
+
# Raises the error found during compilation.
|
48
66
|
def compile!
|
49
67
|
@insts.map.with_index do |inst, idx|
|
50
68
|
@line = idx
|
@@ -53,17 +71,22 @@ module SeccompTools
|
|
53
71
|
when :alu then compile_alu(inst[1], inst[2])
|
54
72
|
when :ret then compile_ret(inst[1])
|
55
73
|
when :cmp then compile_cmp(inst[1], inst[2], inst[3], inst[4])
|
74
|
+
when :jmp_abs then compile_jmp_abs(inst[1])
|
56
75
|
end
|
57
76
|
end
|
58
77
|
rescue ArgumentError => e
|
59
|
-
invalid(@line, e.message)
|
78
|
+
invalid(@insts_linenum[@line], e.message)
|
60
79
|
end
|
61
80
|
|
62
81
|
private
|
63
82
|
|
83
|
+
# Emits a raw BPF object.
|
84
|
+
#
|
85
|
+
# @return [BPF]
|
86
|
+
# Returns the emitted {BPF} object.
|
64
87
|
def emit(*args, k: 0, jt: 0, jf: 0)
|
65
88
|
code = 0
|
66
|
-
# bad idea,
|
89
|
+
# bad idea, but keys are not duplicated so this is ok.
|
67
90
|
args.each do |a|
|
68
91
|
code |= Const::BPF::COMMAND.fetch(a, 0)
|
69
92
|
code |= Const::BPF::JMP.fetch(a, 0)
|
@@ -76,27 +99,37 @@ module SeccompTools
|
|
76
99
|
end
|
77
100
|
|
78
101
|
# A = X / X = A
|
79
|
-
# <A|X>
|
102
|
+
# mem[i] = <A|X>
|
80
103
|
# <A|X> = 123|sys_const
|
81
|
-
# A =
|
104
|
+
# A = len
|
105
|
+
# <A|X> = mem[i]
|
106
|
+
# A = args_h[i]|args[i]|sys_number|arch
|
82
107
|
# A = data[4 * i]
|
83
108
|
def compile_assign(dst, src)
|
84
109
|
# misc txa / tax
|
85
|
-
return
|
86
|
-
|
110
|
+
return compile_assign_misc(dst, src) if (dst == :a && src == :x) || (dst == :x && src == :a)
|
111
|
+
# case of st / stx
|
112
|
+
return emit(src == :x ? :stx : :st, k: dst.last) if dst.is_a?(Array) && dst.first == :mem
|
113
|
+
|
87
114
|
src = evaluate(src)
|
88
|
-
# TODO: handle store case.
|
89
115
|
ld = dst == :x ? :ldx : :ld
|
90
116
|
# <A|X> = <immi>
|
91
117
|
return emit(ld, :imm, k: src) if src.is_a?(Integer)
|
92
|
-
# now src must be in form [:mem/:data, num]
|
93
|
-
return emit(ld,
|
118
|
+
# now src must be in form [:len/:mem/:data, num]
|
119
|
+
return emit(ld, src.first, k: src.last) if src.first == :mem || src.first == :len
|
94
120
|
# check if num is multiple of 4
|
95
|
-
raise ArgumentError, 'Index of data[] must be
|
121
|
+
raise ArgumentError, 'Index of data[] must be a multiple of 4' if src.last % 4 != 0
|
122
|
+
|
96
123
|
emit(ld, :abs, k: src.last)
|
97
124
|
end
|
98
125
|
|
126
|
+
def compile_assign_misc(dst, _src)
|
127
|
+
emit(:misc, dst == :a ? :txa : :tax)
|
128
|
+
end
|
129
|
+
|
99
130
|
def compile_alu(op, val)
|
131
|
+
return emit(:alu, :neg) if op == :neg
|
132
|
+
|
100
133
|
val = evaluate(val)
|
101
134
|
src = val == :x ? :x : :k
|
102
135
|
val = 0 if val == :x
|
@@ -104,9 +137,19 @@ module SeccompTools
|
|
104
137
|
end
|
105
138
|
|
106
139
|
def compile_ret(val)
|
107
|
-
|
140
|
+
if val == :a
|
141
|
+
src = :a
|
142
|
+
val = 0
|
143
|
+
end
|
144
|
+
emit(:ret, src, k: val)
|
108
145
|
end
|
109
146
|
|
147
|
+
def compile_jmp_abs(target)
|
148
|
+
targ = label_offset(target)
|
149
|
+
emit(:jmp, :ja, k: targ)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Compiles comparison.
|
110
153
|
def compile_cmp(op, val, jt, jf)
|
111
154
|
jt = label_offset(jt)
|
112
155
|
jf = label_offset(jf)
|
@@ -120,26 +163,48 @@ module SeccompTools
|
|
120
163
|
return label if label.is_a?(Integer)
|
121
164
|
return 0 if label == 'next'
|
122
165
|
raise ArgumentError, "Undefined label #{label.inspect}" if @labels[label].nil?
|
166
|
+
raise ArgumentError, "Does not support backward jumping to #{label.inspect}" if @labels[label] < @line
|
167
|
+
|
123
168
|
@labels[label] - @line - 1
|
124
169
|
end
|
125
170
|
|
126
171
|
def evaluate(val)
|
127
|
-
return val if val.is_a?(Integer) || val == :x
|
172
|
+
return val if val.is_a?(Integer) || val == :x || val == :a
|
173
|
+
|
128
174
|
# keywords
|
129
175
|
val = case val
|
130
176
|
when 'sys_number' then [:data, 0]
|
131
177
|
when 'arch' then [:data, 4]
|
178
|
+
when 'len' then [:len, 0]
|
132
179
|
else val
|
133
180
|
end
|
134
|
-
return
|
135
|
-
|
181
|
+
return eval_constants(val) if val.is_a?(String)
|
182
|
+
|
183
|
+
# remains are [:mem/:data/:args/:args_h, <num>]
|
136
184
|
# first convert args to data
|
137
185
|
val = [:data, val.last * 8 + 16] if val.first == :args
|
186
|
+
val = [:data, val.last * 8 + 20] if val.first == :args_h
|
138
187
|
val
|
139
188
|
end
|
140
189
|
|
190
|
+
def eval_constants(str)
|
191
|
+
Const::Syscall.const_get(@arch.upcase.to_sym)[str.to_sym] ||
|
192
|
+
Const::Audit::ARCH[str] ||
|
193
|
+
raise(ArgumentError, "Invalid constant: #{str.inspect}")
|
194
|
+
end
|
195
|
+
|
141
196
|
attr_reader :token
|
142
197
|
|
198
|
+
# <goto|jmp|jump> <label|Integer>
|
199
|
+
def jmp_abs
|
200
|
+
token.fetch('goto') ||
|
201
|
+
token.fetch('jmp') ||
|
202
|
+
token.fetch('jump') ||
|
203
|
+
raise(ArgumentError, "Invalid jump alias: #{token.cur.inspect}")
|
204
|
+
target = token.fetch!(:goto)
|
205
|
+
[:jmp_abs, target]
|
206
|
+
end
|
207
|
+
|
143
208
|
# A <comparison> <sys_str|X|Integer> ? <label|Integer> : <label|Integer>
|
144
209
|
def cmp
|
145
210
|
token.fetch!('A')
|
@@ -179,6 +244,7 @@ module SeccompTools
|
|
179
244
|
# A = mem[i]
|
180
245
|
# A = args[i]
|
181
246
|
# A = sys_number|arch
|
247
|
+
# A = len
|
182
248
|
def assign
|
183
249
|
dst = token.fetch!(:ax)
|
184
250
|
token.fetch!('=')
|
@@ -186,10 +252,17 @@ module SeccompTools
|
|
186
252
|
token.fetch(:sys_num_x) ||
|
187
253
|
token.fetch(:ary) ||
|
188
254
|
token.fetch('sys_number') ||
|
189
|
-
token.fetch('arch')
|
255
|
+
token.fetch('arch') ||
|
256
|
+
token.fetch('len') ||
|
257
|
+
raise(ArgumentError, "Invalid source: #{token.cur.inspect}")
|
190
258
|
[:assign, dst, src]
|
191
259
|
end
|
192
260
|
|
261
|
+
# returns same format as assign
|
262
|
+
def store
|
263
|
+
[:assign, token.fetch!(:ary), token.fetch!('=') && token.fetch!(:ax)]
|
264
|
+
end
|
265
|
+
|
193
266
|
def define_label
|
194
267
|
name = token.fetch!(:goto)
|
195
268
|
token.fetch(':')
|
@@ -205,6 +278,11 @@ module SeccompTools
|
|
205
278
|
[:alu, op, src]
|
206
279
|
end
|
207
280
|
|
281
|
+
# A = -A
|
282
|
+
def alu_neg
|
283
|
+
%i[alu neg]
|
284
|
+
end
|
285
|
+
|
208
286
|
def remove_comment(line)
|
209
287
|
line = line.to_s.dup
|
210
288
|
line.slice!(/#.*\Z/m)
|
@@ -213,7 +291,7 @@ module SeccompTools
|
|
213
291
|
|
214
292
|
def invalid(line, extra_msg = nil)
|
215
293
|
message = "Invalid instruction at line #{line + 1}: #{@input[line].inspect}"
|
216
|
-
message += "\
|
294
|
+
message += "\nError: #{extra_msg}" if extra_msg
|
217
295
|
raise ArgumentError, message
|
218
296
|
end
|
219
297
|
end
|
@@ -1,13 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'seccomp-tools/const'
|
2
4
|
require 'seccomp-tools/instruction/alu'
|
3
5
|
|
4
6
|
module SeccompTools
|
5
7
|
module Asm
|
6
|
-
# Fetch tokens from string.
|
7
|
-
#
|
8
|
+
# Fetch tokens from a string.
|
9
|
+
#
|
10
|
+
# Internal used by {Compiler}.
|
11
|
+
# @private
|
8
12
|
class Tokenizer
|
9
13
|
# a valid label
|
10
|
-
LABEL_REGEXP = /[
|
14
|
+
LABEL_REGEXP = /[A-Za-z_]\w*/.freeze
|
11
15
|
attr_accessor :cur
|
12
16
|
|
13
17
|
# @param [String] str
|
@@ -40,7 +44,7 @@ module SeccompTools
|
|
40
44
|
res = case type
|
41
45
|
when String then fetch_str(type) || raise_expected("token #{type.inspect}")
|
42
46
|
when :comparison then fetch_strs(COMPARISON).to_sym || raise_expected('a comparison operator')
|
43
|
-
when :sys_num_x then
|
47
|
+
when :sys_num_x then fetch_sys_num_arch_x || raise_expected("a syscall number or 'X'")
|
44
48
|
when :goto then fetch_number || fetch_label || raise_expected('a number or label name')
|
45
49
|
when :ret then fetch_return || raise(ArgumentError, <<-EOS)
|
46
50
|
Invalid return type: #{cur.inspect}.
|
@@ -64,6 +68,8 @@ Invalid return type: #{cur.inspect}.
|
|
64
68
|
|
65
69
|
def fetch_str(str)
|
66
70
|
return nil unless cur.start_with?(str)
|
71
|
+
return nil if str =~ /\A[A-Za-z0-9_]+\Z/ && cur[str.size] =~ /[A-Za-z0-9_]/
|
72
|
+
|
67
73
|
@last_match_size = str.size
|
68
74
|
str
|
69
75
|
end
|
@@ -71,18 +77,21 @@ Invalid return type: #{cur.inspect}.
|
|
71
77
|
def fetch_ax
|
72
78
|
return :a if fetch_str('A')
|
73
79
|
return :x if fetch_str('X')
|
80
|
+
|
74
81
|
nil
|
75
82
|
end
|
76
83
|
|
77
|
-
def
|
84
|
+
def fetch_sys_num_arch_x
|
78
85
|
return :x if fetch_str('X')
|
79
|
-
|
86
|
+
|
87
|
+
fetch_number || fetch_syscall || fetch_arch
|
80
88
|
end
|
81
89
|
|
82
90
|
# Currently only supports 10-based decimal numbers.
|
83
91
|
def fetch_number
|
84
92
|
res = fetch_regexp(/^0x[0-9a-f]+/) || fetch_regexp(/^[0-9]+/)
|
85
93
|
return nil if res.nil?
|
94
|
+
|
86
95
|
Integer(res)
|
87
96
|
end
|
88
97
|
|
@@ -92,9 +101,14 @@ Invalid return type: #{cur.inspect}.
|
|
92
101
|
fetch_strs(sys.keys.map(&:to_s).sort_by(&:size).reverse)
|
93
102
|
end
|
94
103
|
|
104
|
+
def fetch_arch
|
105
|
+
fetch_strs(Const::Audit::ARCH.keys)
|
106
|
+
end
|
107
|
+
|
95
108
|
def fetch_regexp(regexp)
|
96
109
|
idx = cur =~ regexp
|
97
110
|
return nil if idx.nil? || idx != 0
|
111
|
+
|
98
112
|
match = cur.match(regexp)[0]
|
99
113
|
@last_match_size = match.size
|
100
114
|
match
|
@@ -110,6 +124,7 @@ Invalid return type: #{cur.inspect}.
|
|
110
124
|
regexp = /(#{Const::BPF::ACTION.keys.join('|')})(\([0-9]{1,5}\))?/
|
111
125
|
action = fetch_regexp(regexp)
|
112
126
|
return fetch_str('A') && :a if action.nil?
|
127
|
+
|
113
128
|
# check if action contains '('the next bytes are (<num>)
|
114
129
|
ret_val = 0
|
115
130
|
if action.include?('(')
|
@@ -120,10 +135,11 @@ Invalid return type: #{cur.inspect}.
|
|
120
135
|
end
|
121
136
|
|
122
137
|
def fetch_ary
|
123
|
-
support_name = %w[data mem args]
|
138
|
+
support_name = %w[data mem args args_h]
|
124
139
|
regexp = /(#{support_name.join('|')})\[[0-9]{1,2}\]/
|
125
140
|
match = fetch_regexp(regexp)
|
126
141
|
return nil if match.nil?
|
142
|
+
|
127
143
|
res, val = match.split('[')
|
128
144
|
val = val.to_i
|
129
145
|
[res.to_sym, val]
|
@@ -133,6 +149,7 @@ Invalid return type: #{cur.inspect}.
|
|
133
149
|
ops = %w[+ - * / | & ^ << >>]
|
134
150
|
op = fetch_strs(ops)
|
135
151
|
return nil if op.nil?
|
152
|
+
|
136
153
|
Instruction::ALU::OP_SYM.invert[op.to_sym]
|
137
154
|
end
|
138
155
|
|
@@ -144,7 +161,7 @@ Invalid return type: #{cur.inspect}.
|
|
144
161
|
|
145
162
|
def raise_expected(msg)
|
146
163
|
raise ArgumentError, <<-EOS
|
147
|
-
Expected #{msg}
|
164
|
+
Expected #{msg} but found #{cur.split[0].inspect}.
|
148
165
|
EOS
|
149
166
|
end
|
150
167
|
end
|
data/lib/seccomp-tools/bpf.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'set'
|
4
|
+
require 'stringio'
|
2
5
|
|
3
6
|
require 'seccomp-tools/const'
|
4
7
|
require 'seccomp-tools/instruction/instruction'
|
@@ -30,11 +33,11 @@ module SeccompTools
|
|
30
33
|
# Line number of this filter.
|
31
34
|
def initialize(raw, arch, line)
|
32
35
|
if raw.is_a?(String)
|
33
|
-
io = StringIO.new(raw)
|
34
|
-
@code = io.read(2).
|
36
|
+
io = ::StringIO.new(raw)
|
37
|
+
@code = io.read(2).unpack1('S')
|
35
38
|
@jt = io.read(1).ord
|
36
39
|
@jf = io.read(1).ord
|
37
|
-
@k = io.read(4).
|
40
|
+
@k = io.read(4).unpack1('L')
|
38
41
|
else
|
39
42
|
@code = raw[:code]
|
40
43
|
@jt = raw[:jt]
|
@@ -77,7 +80,7 @@ module SeccompTools
|
|
77
80
|
# @param [Context] context
|
78
81
|
# Current context.
|
79
82
|
# @yieldparam [Integer] pc
|
80
|
-
# Program
|
83
|
+
# Program counter after this instruction.
|
81
84
|
# @yieldparam [Context] ctx
|
82
85
|
# Context after this instruction.
|
83
86
|
# @return [void]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'seccomp-tools/cli/base'
|
2
4
|
require 'seccomp-tools/asm/asm'
|
3
5
|
|
@@ -6,9 +8,9 @@ module SeccompTools
|
|
6
8
|
# Handle 'asm' command.
|
7
9
|
class Asm < Base
|
8
10
|
# Summary of this command.
|
9
|
-
SUMMARY = 'Seccomp bpf assembler.'
|
11
|
+
SUMMARY = 'Seccomp bpf assembler.'
|
10
12
|
# Usage of this command.
|
11
|
-
USAGE =
|
13
|
+
USAGE = "asm - #{SUMMARY}\n\nUsage: seccomp-tools asm IN_FILE [options]"
|
12
14
|
|
13
15
|
def initialize(*)
|
14
16
|
super
|
@@ -24,8 +26,8 @@ module SeccompTools
|
|
24
26
|
option[:ofile] = o
|
25
27
|
end
|
26
28
|
|
27
|
-
opt.on('-f', '--format FORMAT', %i[inspect raw carray],
|
28
|
-
'Output format. FORMAT can only be one of <inspect|raw|
|
29
|
+
opt.on('-f', '--format FORMAT', %i[inspect raw c_array carray c_source assembly],
|
30
|
+
'Output format. FORMAT can only be one of <inspect|raw|c_array|c_source|assembly>.',
|
29
31
|
'Default: inspect') do |f|
|
30
32
|
option[:format] = f
|
31
33
|
end
|
@@ -38,14 +40,22 @@ module SeccompTools
|
|
38
40
|
# @return [void]
|
39
41
|
def handle
|
40
42
|
return unless super
|
43
|
+
|
41
44
|
option[:ifile] = argv.shift
|
42
45
|
return CLI.show(parser.help) if option[:ifile].nil?
|
46
|
+
|
43
47
|
res = SeccompTools::Asm.asm(input, arch: option[:arch])
|
44
48
|
output do
|
45
49
|
case option[:format]
|
46
|
-
when :inspect then res.inspect
|
50
|
+
when :inspect then "#{res.inspect}\n"
|
47
51
|
when :raw then res
|
48
|
-
when :carray then "unsigned char bpf[] = {#{res.bytes.join(',')}};\n"
|
52
|
+
when :c_array, :carray then "unsigned char bpf[] = {#{res.bytes.join(',')}};\n"
|
53
|
+
when :c_source then SeccompTools::Util.template('asm.c').sub('<TO_BE_REPLACED>', res.bytes.join(','))
|
54
|
+
when :assembly
|
55
|
+
SeccompTools::Util.template("asm.#{option[:arch]}.asm").sub(
|
56
|
+
'<TO_BE_REPLACED>',
|
57
|
+
res.bytes.map { |b| format('\\\%03o', b) }.join
|
58
|
+
)
|
49
59
|
end
|
50
60
|
end
|
51
61
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'optparse'
|
2
4
|
|
3
5
|
require 'seccomp-tools/util'
|
@@ -23,10 +25,12 @@ module SeccompTools
|
|
23
25
|
|
24
26
|
# Handle show help message.
|
25
27
|
# @return [Boolean]
|
26
|
-
# For decestors to check if
|
28
|
+
# For decestors to check if need to continue.
|
27
29
|
def handle
|
28
30
|
return CLI.show(parser.help) if argv.empty? || %w[-h --help].any? { |h| argv.include?(h) }
|
31
|
+
|
29
32
|
parser.parse!(argv)
|
33
|
+
option[:arch] ||= Util.system_arch
|
30
34
|
true
|
31
35
|
end
|
32
36
|
|
@@ -35,7 +39,7 @@ module SeccompTools
|
|
35
39
|
# @return [String]
|
36
40
|
# String read from file.
|
37
41
|
def input
|
38
|
-
option[:ifile] == '-' ?
|
42
|
+
option[:ifile] == '-' ? $stdin.read.force_encoding('ascii-8bit') : IO.binread(option[:ifile])
|
39
43
|
end
|
40
44
|
|
41
45
|
# Write data to stdout or file(s).
|
@@ -45,6 +49,7 @@ module SeccompTools
|
|
45
49
|
def output
|
46
50
|
# if file name not present, just output to stdout.
|
47
51
|
return $stdout.write(yield) if option[:ofile].nil?
|
52
|
+
|
48
53
|
# times of calling output
|
49
54
|
@serial ||= 0
|
50
55
|
# Write to file, we should disable colorize
|
@@ -77,7 +82,7 @@ module SeccompTools
|
|
77
82
|
File.join(File.dirname(file), base + suffix) + ext
|
78
83
|
end
|
79
84
|
|
80
|
-
# For
|
85
|
+
# For descendants to define usage message easily.
|
81
86
|
# @return [String]
|
82
87
|
# Usage information.
|
83
88
|
def usage
|
@@ -87,7 +92,8 @@ module SeccompTools
|
|
87
92
|
def option_arch(opt)
|
88
93
|
supported = Util.supported_archs
|
89
94
|
opt.on('-a', '--arch ARCH', supported, 'Specify architecture.',
|
90
|
-
"Supported architectures are <#{supported.join('|')}>."
|
95
|
+
"Supported architectures are <#{supported.join('|')}>.",
|
96
|
+
"Default: #{Util.system_arch}") do |a|
|
91
97
|
option[:arch] = a
|
92
98
|
end
|
93
99
|
end
|