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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +112 -30
  3. data/bin/seccomp-tools +1 -0
  4. data/ext/ptrace/extconf.rb +2 -0
  5. data/ext/ptrace/ptrace.c +107 -5
  6. data/lib/seccomp-tools.rb +5 -0
  7. data/lib/seccomp-tools/asm/asm.rb +5 -2
  8. data/lib/seccomp-tools/asm/compiler.rb +96 -18
  9. data/lib/seccomp-tools/asm/tokenizer.rb +25 -8
  10. data/lib/seccomp-tools/bpf.rb +7 -4
  11. data/lib/seccomp-tools/cli/asm.rb +16 -6
  12. data/lib/seccomp-tools/cli/base.rb +10 -4
  13. data/lib/seccomp-tools/cli/cli.rb +9 -6
  14. data/lib/seccomp-tools/cli/disasm.rb +6 -2
  15. data/lib/seccomp-tools/cli/dump.rb +37 -6
  16. data/lib/seccomp-tools/cli/emu.rb +41 -22
  17. data/lib/seccomp-tools/const.rb +47 -16
  18. data/lib/seccomp-tools/consts/sys_arg.rb +432 -0
  19. data/lib/seccomp-tools/consts/sys_nr/aarch64.rb +284 -0
  20. data/lib/seccomp-tools/consts/{amd64.rb → sys_nr/amd64.rb} +6 -1
  21. data/lib/seccomp-tools/consts/{i386.rb → sys_nr/i386.rb} +18 -15
  22. data/lib/seccomp-tools/disasm/context.rb +125 -34
  23. data/lib/seccomp-tools/disasm/disasm.rb +5 -2
  24. data/lib/seccomp-tools/dumper.rb +75 -8
  25. data/lib/seccomp-tools/emulator.rb +19 -8
  26. data/lib/seccomp-tools/instruction/alu.rb +7 -2
  27. data/lib/seccomp-tools/instruction/base.rb +5 -3
  28. data/lib/seccomp-tools/instruction/instruction.rb +2 -0
  29. data/lib/seccomp-tools/instruction/jmp.rb +28 -14
  30. data/lib/seccomp-tools/instruction/ld.rb +28 -12
  31. data/lib/seccomp-tools/instruction/ldx.rb +2 -0
  32. data/lib/seccomp-tools/instruction/misc.rb +2 -0
  33. data/lib/seccomp-tools/instruction/ret.rb +14 -2
  34. data/lib/seccomp-tools/instruction/st.rb +4 -2
  35. data/lib/seccomp-tools/instruction/stx.rb +2 -0
  36. data/lib/seccomp-tools/logger.rb +40 -0
  37. data/lib/seccomp-tools/syscall.rb +24 -13
  38. data/lib/seccomp-tools/templates/asm.amd64.asm +26 -0
  39. data/lib/seccomp-tools/templates/asm.c +17 -0
  40. data/lib/seccomp-tools/templates/asm.i386.asm +33 -0
  41. data/lib/seccomp-tools/util.rb +24 -3
  42. data/lib/seccomp-tools/version.rb +3 -1
  43. metadata +51 -44
@@ -0,0 +1,284 @@
1
+ # frozen_string_literal: true
2
+
3
+ {
4
+ io_setup: 0,
5
+ io_destroy: 1,
6
+ io_submit: 2,
7
+ io_cancel: 3,
8
+ io_getevents: 4,
9
+ setxattr: 5,
10
+ lsetxattr: 6,
11
+ fsetxattr: 7,
12
+ getxattr: 8,
13
+ lgetxattr: 9,
14
+ fgetxattr: 10,
15
+ listxattr: 11,
16
+ llistxattr: 12,
17
+ flistxattr: 13,
18
+ removexattr: 14,
19
+ lremovexattr: 15,
20
+ fremovexattr: 16,
21
+ getcwd: 17,
22
+ lookup_dcookie: 18,
23
+ eventfd2: 19,
24
+ epoll_create1: 20,
25
+ epoll_ctl: 21,
26
+ epoll_pwait: 22,
27
+ dup: 23,
28
+ dup3: 24,
29
+ fcntl: 25,
30
+ inotify_init1: 26,
31
+ inotify_add_watch: 27,
32
+ inotify_rm_watch: 28,
33
+ ioctl: 29,
34
+ ioprio_set: 30,
35
+ ioprio_get: 31,
36
+ flock: 32,
37
+ mknodat: 33,
38
+ mkdirat: 34,
39
+ unlinkat: 35,
40
+ symlinkat: 36,
41
+ linkat: 37,
42
+ renameat: 38,
43
+ umount2: 39,
44
+ mount: 40,
45
+ pivot_root: 41,
46
+ nfsservctl: 42,
47
+ statfs: 43,
48
+ fstatfs: 44,
49
+ truncate: 45,
50
+ ftruncate: 46,
51
+ fallocate: 47,
52
+ faccessat: 48,
53
+ chdir: 49,
54
+ fchdir: 50,
55
+ chroot: 51,
56
+ fchmod: 52,
57
+ fchmodat: 53,
58
+ fchownat: 54,
59
+ fchown: 55,
60
+ openat: 56,
61
+ close: 57,
62
+ vhangup: 58,
63
+ pipe2: 59,
64
+ quotactl: 60,
65
+ getdents: 61,
66
+ getdents64: 61,
67
+ lseek: 62,
68
+ read: 63,
69
+ write: 64,
70
+ readv: 65,
71
+ writev: 66,
72
+ pread: 67,
73
+ pread64: 67,
74
+ pwrite: 68,
75
+ pwrite64: 68,
76
+ preadv: 69,
77
+ pwritev: 70,
78
+ sendfile: 71,
79
+ pselect6: 72,
80
+ ppoll: 73,
81
+ signalfd4: 74,
82
+ vmsplice: 75,
83
+ splice: 76,
84
+ tee: 77,
85
+ readlinkat: 78,
86
+ newfstatat: 79,
87
+ fstat: 80,
88
+ newfstat: 80,
89
+ sync: 81,
90
+ fsync: 82,
91
+ fdatasync: 83,
92
+ sync_file_range: 84,
93
+ timerfd_create: 85,
94
+ timerfd_settime: 86,
95
+ timerfd_gettime: 87,
96
+ utimensat: 88,
97
+ acct: 89,
98
+ capget: 90,
99
+ capset: 91,
100
+ personality: 92,
101
+ exit: 93,
102
+ exit_group: 94,
103
+ waitid: 95,
104
+ set_tid_address: 96,
105
+ unshare: 97,
106
+ futex: 98,
107
+ set_robust_list: 99,
108
+ get_robust_list: 100,
109
+ nanosleep: 101,
110
+ getitimer: 102,
111
+ setitimer: 103,
112
+ kexec_load: 104,
113
+ init_module: 105,
114
+ delete_module: 106,
115
+ timer_create: 107,
116
+ timer_gettime: 108,
117
+ timer_getoverrun: 109,
118
+ timer_settime: 110,
119
+ timer_delete: 111,
120
+ clock_settime: 112,
121
+ clock_gettime: 113,
122
+ clock_getres: 114,
123
+ clock_nanosleep: 115,
124
+ syslog: 116,
125
+ ptrace: 117,
126
+ sched_setparam: 118,
127
+ sched_setscheduler: 119,
128
+ sched_getscheduler: 120,
129
+ sched_getparam: 121,
130
+ sched_setaffinity: 122,
131
+ sched_getaffinity: 123,
132
+ sched_yield: 124,
133
+ sched_get_priority_max: 125,
134
+ sched_get_priority_min: 126,
135
+ sched_rr_get_interval: 127,
136
+ restart_syscall: 128,
137
+ kill: 129,
138
+ tkill: 130,
139
+ tgkill: 131,
140
+ sigaltstack: 132,
141
+ rt_sigsuspend: 133,
142
+ rt_sigaction: 134,
143
+ rt_sigprocmask: 135,
144
+ rt_sigpending: 136,
145
+ rt_sigtimedwait: 137,
146
+ rt_sigqueueinfo: 138,
147
+ rt_sigreturn: 139,
148
+ setpriority: 140,
149
+ getpriority: 141,
150
+ reboot: 142,
151
+ setregid: 143,
152
+ setgid: 144,
153
+ setreuid: 145,
154
+ setuid: 146,
155
+ setresuid: 147,
156
+ getresuid: 148,
157
+ setresgid: 149,
158
+ getresgid: 150,
159
+ setfsuid: 151,
160
+ setfsgid: 152,
161
+ times: 153,
162
+ setpgid: 154,
163
+ getpgid: 155,
164
+ getsid: 156,
165
+ setsid: 157,
166
+ getgroups: 158,
167
+ setgroups: 159,
168
+ uname: 160,
169
+ sethostname: 161,
170
+ setdomainname: 162,
171
+ getrlimit: 163,
172
+ setrlimit: 164,
173
+ getrusage: 165,
174
+ umask: 166,
175
+ prctl: 167,
176
+ getcpu: 168,
177
+ gettimeofday: 169,
178
+ settimeofday: 170,
179
+ adjtimex: 171,
180
+ getpid: 172,
181
+ getppid: 173,
182
+ getuid: 174,
183
+ geteuid: 175,
184
+ getgid: 176,
185
+ getegid: 177,
186
+ gettid: 178,
187
+ sysinfo: 179,
188
+ mq_open: 180,
189
+ mq_unlink: 181,
190
+ mq_timedsend: 182,
191
+ mq_timedreceive: 183,
192
+ mq_notify: 184,
193
+ mq_getsetattr: 185,
194
+ msgget: 186,
195
+ msgctl: 187,
196
+ msgrcv: 188,
197
+ msgsnd: 189,
198
+ semget: 190,
199
+ semctl: 191,
200
+ semtimedop: 192,
201
+ semop: 193,
202
+ shmget: 194,
203
+ shmctl: 195,
204
+ shmat: 196,
205
+ shmdt: 197,
206
+ socket: 198,
207
+ socketpair: 199,
208
+ bind: 200,
209
+ listen: 201,
210
+ accept: 202,
211
+ connect: 203,
212
+ getsockname: 204,
213
+ getpeername: 205,
214
+ sendto: 206,
215
+ recvfrom: 207,
216
+ setsockopt: 208,
217
+ getsockopt: 209,
218
+ shutdown: 210,
219
+ sendmsg: 211,
220
+ recvmsg: 212,
221
+ readahead: 213,
222
+ brk: 214,
223
+ munmap: 215,
224
+ mremap: 216,
225
+ add_key: 217,
226
+ request_key: 218,
227
+ keyctl: 219,
228
+ clone: 220,
229
+ execve: 221,
230
+ mmap: 222,
231
+ fadvise64: 223,
232
+ swapon: 224,
233
+ swapoff: 225,
234
+ mprotect: 226,
235
+ msync: 227,
236
+ mlock: 228,
237
+ munlock: 229,
238
+ mlockall: 230,
239
+ munlockall: 231,
240
+ mincore: 232,
241
+ madvise: 233,
242
+ remap_file_pages: 234,
243
+ mbind: 235,
244
+ get_mempolicy: 236,
245
+ set_mempolicy: 237,
246
+ migrate_pages: 238,
247
+ move_pages: 239,
248
+ rt_tgsigqueueinfo: 240,
249
+ perf_event_open: 241,
250
+ accept4: 242,
251
+ recvmmsg: 243,
252
+ wait4: 260,
253
+ prlimit64: 261,
254
+ fanotify_init: 262,
255
+ fanotify_mark: 263,
256
+ name_to_handle_at: 264,
257
+ open_by_handle_at: 265,
258
+ clock_adjtime: 266,
259
+ syncfs: 267,
260
+ setns: 268,
261
+ sendmmsg: 269,
262
+ process_vm_readv: 270,
263
+ process_vm_writev: 271,
264
+ kcmp: 272,
265
+ finit_module: 273,
266
+ sched_setattr: 274,
267
+ sched_getattr: 275,
268
+ renameat2: 276,
269
+ seccomp: 277,
270
+ getrandom: 278,
271
+ memfd_create: 279,
272
+ bpf: 280,
273
+ execveat: 281,
274
+ userfaultfd: 282,
275
+ membarrier: 283,
276
+ mlock2: 284,
277
+ copy_file_range: 285,
278
+ preadv2: 286,
279
+ pwritev2: 287,
280
+ pkey_mprotect: 288,
281
+ pkey_alloc: 289,
282
+ pkey_free: 290,
283
+ statx: 291
284
+ }
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ X32_MODE_BIT = 0x40000000
1
4
  {
2
5
  read: 0,
3
6
  write: 1,
@@ -17,7 +20,9 @@
17
20
  rt_sigreturn: 15,
18
21
  ioctl: 16,
19
22
  pread: 17,
23
+ pread64: 17,
20
24
  pwrite: 18,
25
+ pwrite64: 18,
21
26
  readv: 19,
22
27
  writev: 20,
23
28
  access: 21,
@@ -332,4 +337,4 @@
332
337
  pkey_alloc: 330,
333
338
  pkey_free: 331,
334
339
  statx: 332
335
- }
340
+ }.tap { |h| h.keys.each { |k| h["x32_#{k}".to_sym] = h[k] | X32_MODE_BIT } } # rubocop:disable Style/HashEachMethods
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  {
4
+ restart_syscall: 0,
2
5
  exit: 1,
3
6
  fork: 2,
4
7
  read: 3,
@@ -178,8 +181,8 @@
178
181
  rt_sigtimedwait: 177,
179
182
  rt_sigqueueinfo: 178,
180
183
  rt_sigsuspend: 179,
181
- pread: 180,
182
- pwrite: 181,
184
+ pread64: 180,
185
+ pwrite64: 181,
183
186
  chown: 182,
184
187
  getcwd: 183,
185
188
  capget: 184,
@@ -256,14 +259,14 @@
256
259
  remap_file_pages: 257,
257
260
  set_tid_address: 258,
258
261
  timer_create: 259,
259
- timer_settime: (259 + 1),
260
- timer_gettime: (259 + 2),
261
- timer_getoverrun: (259 + 3),
262
- timer_delete: (259 + 4),
263
- clock_settime: (259 + 5),
264
- clock_gettime: (259 + 6),
265
- clock_getres: (259 + 7),
266
- clock_nanosleep: (259 + 8),
262
+ timer_settime: 260,
263
+ timer_gettime: 261,
264
+ timer_getoverrun: 262,
265
+ timer_delete: 263,
266
+ clock_settime: 264,
267
+ clock_gettime: 265,
268
+ clock_getres: 266,
269
+ clock_nanosleep: 267,
267
270
  statfs64: 268,
268
271
  fstatfs64: 269,
269
272
  tgkill: 270,
@@ -274,11 +277,11 @@
274
277
  get_mempolicy: 275,
275
278
  set_mempolicy: 276,
276
279
  mq_open: 277,
277
- mq_unlink: (277 + 1),
278
- mq_timedsend: (277 + 2),
279
- mq_timedreceive: (277 + 3),
280
- mq_notify: (277 + 4),
281
- mq_getsetattr: (277 + 5),
280
+ mq_unlink: 278,
281
+ mq_timedsend: 279,
282
+ mq_timedreceive: 280,
283
+ mq_notify: 281,
284
+ mq_getsetattr: 282,
282
285
  sys_kexec_load: 283,
283
286
  waitid: 284,
284
287
  add_key: 286,
@@ -1,79 +1,170 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SeccompTools
2
4
  module Disasm
5
+ # @private
6
+ #
3
7
  # Context for disassembler to analyze.
4
8
  #
5
- # This context only care if +reg/mem+ can be one of +data[*]+.
9
+ # This class maintains:
10
+ # * if +reg/mem+ can be one of +data[*]+
11
+ # * if +data[0]+ (i.e. sys_number) is a known value
6
12
  class Context
7
- # @return [Hash{Integer, Symbol => Integer?}] Records reg and mem values.
13
+ # @private
14
+ #
15
+ # Records the type and value.
16
+ class Value
17
+ attr_reader :val # @return [Integer]
18
+
19
+ # @param [:imm, :data, :mem] rel
20
+ # @param [Integer?] val
21
+ def initialize(rel: :imm, val: nil)
22
+ @rel = rel
23
+ @val = val
24
+ end
25
+
26
+ # @return [Boolean]
27
+ def data?
28
+ @rel == :data
29
+ end
30
+
31
+ # @return [Boolean]
32
+ def imm?
33
+ @rel == :imm && @val.is_a?(Integer)
34
+ end
35
+
36
+ # Defines hash function.
37
+ # @return [Integer]
38
+ def hash
39
+ @rel.hash ^ @val.hash
40
+ end
41
+
42
+ # Defines +eql?+.
43
+ #
44
+ # @param [Context::Value] other
45
+ # @return [Boolean]
46
+ def eql?(other)
47
+ @val == other.val && @rel == other.instance_variable_get(:@rel)
48
+ end
49
+ end
50
+
51
+ # @return [{Integer, Symbol => Context::Value}] Records reg and mem values.
8
52
  attr_reader :values
53
+ # @return [Array<Integer?>] Records the known value of data.
54
+ attr_reader :known_data
9
55
 
10
56
  # Instantiate a {Context} object.
11
- # @param [Integer?] a
12
- # Value to be set to +A+ register.
13
- # @param [Integer?] x
14
- # Value to be set to +X+ register.
15
- # @param [Hash{Integer => Integer?}] mem
16
- # Value to be set to +mem+.
17
- def initialize(a: nil, x: nil, mem: {})
18
- @values = mem
19
- 16.times { |i| @values[i] ||= nil } # make @values always has all keys
20
- @values[:a] = a
21
- @values[:x] = x
57
+ # @param [{Integer, Symbol => Context::Value?}] values
58
+ # Value to be set to +reg/mem+.
59
+ # @param [Array<Integer?>] known_data
60
+ # Records which index of data is known.
61
+ # It's used for tracking if the syscall number is known, which can be used to display argument names of the
62
+ # syscall.
63
+ def initialize(values: {}, known_data: [])
64
+ @values = values
65
+ 16.times { |i| @values[i] ||= Value.new(rel: :mem, val: i) } # make @values always has all keys
66
+ @values[:a] ||= Value.new
67
+ @values[:x] ||= Value.new
68
+ @known_data = known_data
22
69
  end
23
70
 
24
- # Implement a deep dup.
71
+ # Is used for the ld/ldx instructions.
72
+ #
73
+ # @param [#downcase, :a, :x] reg
74
+ # Register to be set
75
+ # @return [void]
76
+ def load(reg, rel: nil, val: nil)
77
+ reg = reg.downcase.to_sym
78
+ values[reg] = if rel == :mem
79
+ values[val]
80
+ else
81
+ Value.new(rel: rel, val: val)
82
+ end
83
+ end
84
+
85
+ # Is used for the st/stx instructions.
86
+ #
87
+ # @param [Integer] idx
88
+ # Index of +mem+ array.
89
+ # @param [#downcase, :a, :x] reg
90
+ # Register.
91
+ #
92
+ # @return [void]
93
+ def store(idx, reg)
94
+ raise RangeError, "Expect 0 <= idx < 16, got #{idx}." unless idx.between?(0, 15)
95
+
96
+ values[idx] = values[reg.downcase.to_sym]
97
+ end
98
+
99
+ # Hints context that current value of register A equals to +val+.
100
+ #
101
+ # @param [Integer, :x] val
102
+ # An immediate value or the symbol x.
103
+ # @return [self]
104
+ # Returns the object itself.
105
+ def eql!(val)
106
+ tap do
107
+ # only cares if A is fetched from data
108
+ next unless a.data?
109
+ next known_data[a.val] = val if val.is_a?(Integer)
110
+ # A == X, we can handle these cases:
111
+ # * X is an immi
112
+ # * X is a known data
113
+ next unless x.data? || x.imm?
114
+ next known_data[a.val] = x.val if x.imm?
115
+
116
+ known_data[a.val] = known_data[x.val]
117
+ end
118
+ end
119
+
120
+ # Implements a deep dup.
25
121
  # @return [Context]
26
122
  def dup
27
- Context.new(a: a, x: x, mem: values.dup)
123
+ Context.new(values: values.dup, known_data: known_data.dup)
28
124
  end
29
125
 
30
126
  # Register A.
31
- # @return [Integer?]
127
+ # @return [Context::Value]
32
128
  def a
33
129
  values[:a]
34
130
  end
35
131
 
36
132
  # Register X.
37
- # @return [Integer?]
133
+ # @return [Context::Value]
38
134
  def x
39
135
  values[:x]
40
136
  end
41
137
 
42
138
  # For conveniently get instance variable.
43
139
  # @param [String, Symbol, Integer] key
44
- # @return [Integer?]
140
+ # @return [Context::Value]
45
141
  def [](key)
46
142
  return values[key] if key.is_a?(Integer) # mem
143
+
47
144
  values[key.downcase.to_sym]
48
145
  end
49
146
 
50
- # For conveniently set instance variable.
51
- # @param [#downcase, Integer] key
52
- # Can be +'A', 'a', :a, 'X', 'x', :x+ or an integer.
53
- # @param [Integer?] val
147
+ # For conveniently set an instance variable.
148
+ # @param [#downcase, :a, :x] reg
149
+ # Can be +'A', 'a', :a, 'X', 'x', :x+.
150
+ # @param [Value] val
54
151
  # Value to set.
55
152
  # @return [void]
56
- def []=(key, val)
57
- if key.is_a?(Integer)
58
- raise RangeError, "Expect 0 <= key < 16, got #{key}." unless key.between?(0, 15)
59
- raise RangeError, "Expect 0 <= val < 64, got #{val}." unless val.nil? || val.between?(0, 63)
60
- values[key] = val
61
- else
62
- values[key.downcase.to_sym] = val
63
- end
153
+ def []=(reg, val)
154
+ values[reg.downcase.to_sym] = val
64
155
  end
65
156
 
66
- # For +Set+ to compare two {Context} object.
157
+ # For +Set+ to compare two {Context} objects.
67
158
  # @param [Context] other
68
159
  # @return [Boolean]
69
160
  def eql?(other)
70
- values.eql?(other.values)
161
+ values.eql?(other.values) && known_data.eql?(other.known_data)
71
162
  end
72
163
 
73
- # For +Set+ to get hash key.
164
+ # For +Set+ to get the hash value.
74
165
  # @return [Integer]
75
166
  def hash
76
- values.hash
167
+ values.hash ^ known_data.hash
77
168
  end
78
169
  end
79
170
  end