seccomp-tools 1.4.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +105 -17
  3. data/ext/ptrace/ptrace.c +56 -4
  4. data/lib/seccomp-tools/asm/asm.rb +8 -6
  5. data/lib/seccomp-tools/asm/compiler.rb +130 -224
  6. data/lib/seccomp-tools/asm/sasm.tab.rb +780 -0
  7. data/lib/seccomp-tools/asm/sasm.y +175 -0
  8. data/lib/seccomp-tools/asm/scalar.rb +129 -0
  9. data/lib/seccomp-tools/asm/scanner.rb +163 -0
  10. data/lib/seccomp-tools/asm/statement.rb +32 -0
  11. data/lib/seccomp-tools/asm/token.rb +29 -0
  12. data/lib/seccomp-tools/bpf.rb +31 -7
  13. data/lib/seccomp-tools/cli/asm.rb +3 -3
  14. data/lib/seccomp-tools/cli/base.rb +4 -4
  15. data/lib/seccomp-tools/cli/disasm.rb +27 -3
  16. data/lib/seccomp-tools/cli/dump.rb +4 -2
  17. data/lib/seccomp-tools/cli/emu.rb +1 -4
  18. data/lib/seccomp-tools/const.rb +37 -3
  19. data/lib/seccomp-tools/consts/sys_nr/aarch64.rb +284 -0
  20. data/lib/seccomp-tools/consts/sys_nr/amd64.rb +5 -1
  21. data/lib/seccomp-tools/consts/sys_nr/i386.rb +14 -14
  22. data/lib/seccomp-tools/consts/sys_nr/s390x.rb +365 -0
  23. data/lib/seccomp-tools/disasm/context.rb +2 -2
  24. data/lib/seccomp-tools/disasm/disasm.rb +16 -9
  25. data/lib/seccomp-tools/dumper.rb +12 -3
  26. data/lib/seccomp-tools/emulator.rb +5 -9
  27. data/lib/seccomp-tools/error.rb +31 -0
  28. data/lib/seccomp-tools/instruction/alu.rb +1 -1
  29. data/lib/seccomp-tools/instruction/base.rb +1 -1
  30. data/lib/seccomp-tools/instruction/jmp.rb +28 -10
  31. data/lib/seccomp-tools/instruction/ld.rb +5 -3
  32. data/lib/seccomp-tools/syscall.rb +23 -13
  33. data/lib/seccomp-tools/templates/asm.s390x.asm +26 -0
  34. data/lib/seccomp-tools/util.rb +3 -1
  35. data/lib/seccomp-tools/version.rb +1 -1
  36. metadata +38 -9
  37. data/lib/seccomp-tools/asm/tokenizer.rb +0 -169
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'os'
4
+
3
5
  require 'seccomp-tools/const'
4
- require 'seccomp-tools/ptrace'
6
+ require 'seccomp-tools/ptrace' if OS.linux?
5
7
 
6
8
  module SeccompTools
7
9
  # Record syscall number, arguments, return value.
@@ -9,12 +11,16 @@ module SeccompTools
9
11
  # Syscall arguments offset of +struct user+ in different arch.
10
12
  ABI = {
11
13
  amd64: { number: 120, args: [112, 104, 96, 56, 72, 44], ret: 80, SYS_prctl: 157, SYS_seccomp: 317 },
12
- i386: { number: 120, args: [40, 88, 96, 104, 112, 32], ret: 80, SYS_prctl: 172, SYS_seccomp: 354 }
14
+ i386: { number: 44, args: [0, 4, 8, 12, 16, 20], ret: 24, SYS_prctl: 172, SYS_seccomp: 354 },
15
+ aarch64: { number: 64, args: [0, 8, 16, 24, 32, 40, 48], ret: 0, SYS_prctl: 167, SYS_seccomp: 277 },
16
+ # Most software invokes syscalls through "svc 0", in which case the syscall number is in r1.
17
+ # However, it's also possible to use "svc NR": this case is not handled here.
18
+ s390x: { number: 24, args: [32, 40, 48, 56, 64, 72], ret: 32, SYS_prctl: 172, SYS_seccomp: 348 }
13
19
  }.freeze
14
20
 
15
21
  # @return [Integer] Process id.
16
22
  attr_reader :pid
17
- # @return [Hash{Symbol => Integer, Array<Integer>}] See {ABI}.
23
+ # @return [{Symbol => Integer, Array<Integer>}] See {ABI}.
18
24
  attr_reader :abi
19
25
  # @return [Integer] Syscall number.
20
26
  attr_reader :number
@@ -60,25 +66,29 @@ module SeccompTools
60
66
  # Architecture of this syscall.
61
67
  def arch
62
68
  @arch ||= File.open("/proc/#{pid}/exe", 'rb') do |f|
63
- f.pos = 4
64
- case f.read(1).ord
65
- when 1 then :i386
66
- when 2 then :amd64
67
- end
69
+ f.pos = 18
70
+ {
71
+ "\x03\x00" => :i386,
72
+ "\x3e\x00" => :amd64,
73
+ "\xb7\x00" => :aarch64,
74
+ "\x00\x16" => :s390x
75
+ }[f.read(2)]
68
76
  end
69
77
  end
70
78
 
71
79
  private
72
80
 
73
81
  def bits
74
- case arch
75
- when :i386 then 32
76
- when :amd64 then 64
77
- end
82
+ {
83
+ i386: 32,
84
+ amd64: 64,
85
+ aarch64: 64,
86
+ s390x: 64
87
+ }[arch]
78
88
  end
79
89
 
80
90
  def peek(offset)
81
- Ptrace.peekuser(pid, offset, 0)
91
+ Ptrace.peekuser(pid, offset, 0, bits)
82
92
  end
83
93
  end
84
94
  end
@@ -0,0 +1,26 @@
1
+ .globl install_seccomp
2
+ install_seccomp:
3
+ lghi %r1, 172 /* __NR_prctl */
4
+ lghi %r2, 38 /* PR_SET_NO_NEW_PRIVS */
5
+ lghi %r3, 1
6
+ xgr %r4, %r4
7
+ xgr %r5, %r5
8
+ xgr %r6, %r6
9
+ svc 0
10
+
11
+ lghi %r1, 172 /* __NR_prctl */
12
+ lghi %r2, 22 /* PR_SET_SECCOMP */
13
+ lghi %r3, 2 /* SECCOMP_MODE_FILTER */
14
+ aghi %r15, -16 /* sizeof(struct sock_fprog) */
15
+ mvhhi 0(%r15), (_filter_end - _filter) >> 3 /* .len */
16
+ larl %r4, _filter
17
+ stg %r4, 8(%r15) /* .filter */
18
+ lgr %r4, %r15
19
+ svc 0
20
+ aghi %r15, 16
21
+
22
+ br %r14
23
+
24
+ _filter:
25
+ .ascii "<TO_BE_REPLACED>"
26
+ _filter_end:
@@ -20,6 +20,8 @@ module SeccompTools
20
20
  case RbConfig::CONFIG['host_cpu']
21
21
  when /x86_64/ then :amd64
22
22
  when /i386/ then :i386
23
+ when /aarch64/ then :aarch64
24
+ when /s390x/ then :s390x
23
25
  else :unknown
24
26
  end
25
27
  end
@@ -77,7 +79,7 @@ module SeccompTools
77
79
  # @return [String]
78
80
  # Content of the file.
79
81
  def template(filename)
80
- IO.binread(File.join(__dir__, 'templates', filename))
82
+ File.binread(File.join(__dir__, 'templates', filename))
81
83
  end
82
84
  end
83
85
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module SeccompTools
4
4
  # Gem version.
5
- VERSION = '1.4.0'
5
+ VERSION = '1.6.0'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seccomp-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - david942j
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-16 00:00:00.000000000 Z
11
+ date: 2023-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -58,28 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.79'
61
+ version: '1'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.79'
68
+ version: '1'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: simplecov
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.17.0
75
+ version: '0.21'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.17.0
82
+ version: '0.21'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: yard
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,26 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0.9'
97
+ - !ruby/object:Gem::Dependency
98
+ name: os
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.1'
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 1.1.1
107
+ type: :runtime
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - "~>"
112
+ - !ruby/object:Gem::Version
113
+ version: '1.1'
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 1.1.1
97
117
  description: |
98
118
  Provide useful tools to analyze seccomp rules.
99
119
  Visit https://github.com/david942j/seccomp-tools for more details.
@@ -112,7 +132,12 @@ files:
112
132
  - lib/seccomp-tools.rb
113
133
  - lib/seccomp-tools/asm/asm.rb
114
134
  - lib/seccomp-tools/asm/compiler.rb
115
- - lib/seccomp-tools/asm/tokenizer.rb
135
+ - lib/seccomp-tools/asm/sasm.tab.rb
136
+ - lib/seccomp-tools/asm/sasm.y
137
+ - lib/seccomp-tools/asm/scalar.rb
138
+ - lib/seccomp-tools/asm/scanner.rb
139
+ - lib/seccomp-tools/asm/statement.rb
140
+ - lib/seccomp-tools/asm/token.rb
116
141
  - lib/seccomp-tools/bpf.rb
117
142
  - lib/seccomp-tools/cli/asm.rb
118
143
  - lib/seccomp-tools/cli/base.rb
@@ -122,12 +147,15 @@ files:
122
147
  - lib/seccomp-tools/cli/emu.rb
123
148
  - lib/seccomp-tools/const.rb
124
149
  - lib/seccomp-tools/consts/sys_arg.rb
150
+ - lib/seccomp-tools/consts/sys_nr/aarch64.rb
125
151
  - lib/seccomp-tools/consts/sys_nr/amd64.rb
126
152
  - lib/seccomp-tools/consts/sys_nr/i386.rb
153
+ - lib/seccomp-tools/consts/sys_nr/s390x.rb
127
154
  - lib/seccomp-tools/disasm/context.rb
128
155
  - lib/seccomp-tools/disasm/disasm.rb
129
156
  - lib/seccomp-tools/dumper.rb
130
157
  - lib/seccomp-tools/emulator.rb
158
+ - lib/seccomp-tools/error.rb
131
159
  - lib/seccomp-tools/instruction/alu.rb
132
160
  - lib/seccomp-tools/instruction/base.rb
133
161
  - lib/seccomp-tools/instruction/instruction.rb
@@ -143,6 +171,7 @@ files:
143
171
  - lib/seccomp-tools/templates/asm.amd64.asm
144
172
  - lib/seccomp-tools/templates/asm.c
145
173
  - lib/seccomp-tools/templates/asm.i386.asm
174
+ - lib/seccomp-tools/templates/asm.s390x.asm
146
175
  - lib/seccomp-tools/util.rb
147
176
  - lib/seccomp-tools/version.rb
148
177
  homepage:
@@ -161,14 +190,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
161
190
  requirements:
162
191
  - - ">="
163
192
  - !ruby/object:Gem::Version
164
- version: '2.4'
193
+ version: '2.6'
165
194
  required_rubygems_version: !ruby/object:Gem::Requirement
166
195
  requirements:
167
196
  - - ">="
168
197
  - !ruby/object:Gem::Version
169
198
  version: '0'
170
199
  requirements: []
171
- rubygems_version: 3.0.3
200
+ rubygems_version: 3.1.6
172
201
  signing_key:
173
202
  specification_version: 4
174
203
  summary: seccomp-tools
@@ -1,169 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'seccomp-tools/const'
4
- require 'seccomp-tools/instruction/alu'
5
-
6
- module SeccompTools
7
- module Asm
8
- # Fetch tokens from a string.
9
- #
10
- # Internal used by {Compiler}.
11
- # @private
12
- class Tokenizer
13
- # a valid label
14
- LABEL_REGEXP = /[A-Za-z_]\w*/.freeze
15
- attr_accessor :cur
16
-
17
- # @param [String] str
18
- # @example
19
- # Tokenizer.new('return ALLOW')
20
- def initialize(str)
21
- @str = str
22
- @cur = @str.dup
23
- end
24
-
25
- # Fetch a token without raising errors.
26
- def fetch(type)
27
- fetch!(type)
28
- rescue ArgumentError
29
- nil
30
- end
31
-
32
- # Fetch a token. When expected token is not found,
33
- # error with proper message would be raised.
34
- #
35
- # @param [String, Symbol] type
36
- # @example
37
- # tokenizer = Tokenizer.new('return ALLOW')
38
- # tokenfizer.fetch!('return')
39
- # #=> "return"
40
- # tokenizer.fetch!(:ret)
41
- # #=> 2147418112
42
- def fetch!(type)
43
- @last_match_size = 0
44
- res = case type
45
- when String then fetch_str(type) || raise_expected("token #{type.inspect}")
46
- when :comparison then fetch_strs(COMPARISON).to_sym || raise_expected('a comparison operator')
47
- when :sys_num_x then fetch_sys_num_arch_x || raise_expected("a syscall number or 'X'")
48
- when :goto then fetch_number || fetch_label || raise_expected('a number or label name')
49
- when :ret then fetch_return || raise(ArgumentError, <<-EOS)
50
- Invalid return type: #{cur.inspect}.
51
- EOS
52
- when :ax then fetch_ax || raise_expected("'A' or 'X'")
53
- when :ary then fetch_ary || raise_expected('data[<num>], mem[<num>], or args[<num>]')
54
- when :alu_op then fetch_alu || raise_expected('an ALU operator')
55
- else raise ArgumentError, "Unsupported type: #{type.inspect}"
56
- end
57
- slice!
58
- res
59
- end
60
-
61
- private
62
-
63
- COMPARISON = %w[== != <= >= < >].freeze
64
-
65
- def fetch_strs(strs)
66
- strs.find(&method(:fetch_str))
67
- end
68
-
69
- def fetch_str(str)
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
-
73
- @last_match_size = str.size
74
- str
75
- end
76
-
77
- def fetch_ax
78
- return :a if fetch_str('A')
79
- return :x if fetch_str('X')
80
-
81
- nil
82
- end
83
-
84
- def fetch_sys_num_arch_x
85
- return :x if fetch_str('X')
86
-
87
- fetch_number || fetch_syscall || fetch_arch
88
- end
89
-
90
- # Currently only supports 10-based decimal numbers.
91
- def fetch_number
92
- res = fetch_regexp(/^0x[0-9a-f]+/) || fetch_regexp(/^[0-9]+/)
93
- return nil if res.nil?
94
-
95
- Integer(res)
96
- end
97
-
98
- def fetch_syscall
99
- sys = Const::Syscall::AMD64
100
- sys = sys.merge(Const::Syscall::I386)
101
- fetch_strs(sys.keys.map(&:to_s).sort_by(&:size).reverse)
102
- end
103
-
104
- def fetch_arch
105
- fetch_strs(Const::Audit::ARCH.keys)
106
- end
107
-
108
- def fetch_regexp(regexp)
109
- idx = cur =~ regexp
110
- return nil if idx.nil? || idx != 0
111
-
112
- match = cur.match(regexp)[0]
113
- @last_match_size = match.size
114
- match
115
- end
116
-
117
- def fetch_label
118
- fetch_regexp(LABEL_REGEXP)
119
- end
120
-
121
- # Convert <type>(num) into return value according to {Const::ACTION}
122
- # @return [Integer, :a]
123
- def fetch_return
124
- regexp = /(#{Const::BPF::ACTION.keys.join('|')})(\([0-9]{1,5}\))?/
125
- action = fetch_regexp(regexp)
126
- return fetch_str('A') && :a if action.nil?
127
-
128
- # check if action contains '('the next bytes are (<num>)
129
- ret_val = 0
130
- if action.include?('(')
131
- action, val = action.split('(')
132
- ret_val = val.to_i
133
- end
134
- Const::BPF::ACTION[action.to_sym] | ret_val
135
- end
136
-
137
- def fetch_ary
138
- support_name = %w[data mem args args_h]
139
- regexp = /(#{support_name.join('|')})\[[0-9]{1,2}\]/
140
- match = fetch_regexp(regexp)
141
- return nil if match.nil?
142
-
143
- res, val = match.split('[')
144
- val = val.to_i
145
- [res.to_sym, val]
146
- end
147
-
148
- def fetch_alu
149
- ops = %w[+ - * / | & ^ << >>]
150
- op = fetch_strs(ops)
151
- return nil if op.nil?
152
-
153
- Instruction::ALU::OP_SYM.invert[op.to_sym]
154
- end
155
-
156
- def slice!
157
- ret = cur.slice!(0, @last_match_size)
158
- cur.strip!
159
- ret
160
- end
161
-
162
- def raise_expected(msg)
163
- raise ArgumentError, <<-EOS
164
- Expected #{msg} but found #{cur.split[0].inspect}.
165
- EOS
166
- end
167
- end
168
- end
169
- end