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.
- checksums.yaml +4 -4
- data/README.md +105 -17
- data/ext/ptrace/ptrace.c +56 -4
- data/lib/seccomp-tools/asm/asm.rb +8 -6
- data/lib/seccomp-tools/asm/compiler.rb +130 -224
- data/lib/seccomp-tools/asm/sasm.tab.rb +780 -0
- data/lib/seccomp-tools/asm/sasm.y +175 -0
- data/lib/seccomp-tools/asm/scalar.rb +129 -0
- data/lib/seccomp-tools/asm/scanner.rb +163 -0
- data/lib/seccomp-tools/asm/statement.rb +32 -0
- data/lib/seccomp-tools/asm/token.rb +29 -0
- data/lib/seccomp-tools/bpf.rb +31 -7
- data/lib/seccomp-tools/cli/asm.rb +3 -3
- data/lib/seccomp-tools/cli/base.rb +4 -4
- data/lib/seccomp-tools/cli/disasm.rb +27 -3
- data/lib/seccomp-tools/cli/dump.rb +4 -2
- data/lib/seccomp-tools/cli/emu.rb +1 -4
- data/lib/seccomp-tools/const.rb +37 -3
- data/lib/seccomp-tools/consts/sys_nr/aarch64.rb +284 -0
- data/lib/seccomp-tools/consts/sys_nr/amd64.rb +5 -1
- data/lib/seccomp-tools/consts/sys_nr/i386.rb +14 -14
- data/lib/seccomp-tools/consts/sys_nr/s390x.rb +365 -0
- data/lib/seccomp-tools/disasm/context.rb +2 -2
- data/lib/seccomp-tools/disasm/disasm.rb +16 -9
- data/lib/seccomp-tools/dumper.rb +12 -3
- data/lib/seccomp-tools/emulator.rb +5 -9
- data/lib/seccomp-tools/error.rb +31 -0
- data/lib/seccomp-tools/instruction/alu.rb +1 -1
- data/lib/seccomp-tools/instruction/base.rb +1 -1
- data/lib/seccomp-tools/instruction/jmp.rb +28 -10
- data/lib/seccomp-tools/instruction/ld.rb +5 -3
- data/lib/seccomp-tools/syscall.rb +23 -13
- data/lib/seccomp-tools/templates/asm.s390x.asm +26 -0
- data/lib/seccomp-tools/util.rb +3 -1
- data/lib/seccomp-tools/version.rb +1 -1
- metadata +38 -9
- 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:
|
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 [
|
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 =
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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:
|
data/lib/seccomp-tools/util.rb
CHANGED
@@ -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
|
-
|
82
|
+
File.binread(File.join(__dir__, 'templates', filename))
|
81
83
|
end
|
82
84
|
end
|
83
85
|
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
|
+
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:
|
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: '
|
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: '
|
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.
|
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.
|
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/
|
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.
|
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.
|
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
|