seccomp-tools 1.4.0 → 1.6.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.
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