seccomp-tools 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2726a64dc089ec7c492cedad9a98d500c656dce84ca593a505d95a42cd07906c
4
- data.tar.gz: c8d3eec04aa38ead5bac1727bb4a1a29199283e648b902edb38df2a7fc4e539f
3
+ metadata.gz: fa755fd2e7ed97279b094dfa28bd668aef4ee638005f0b38405066502fc8a30d
4
+ data.tar.gz: 56b0d51796d97a89f67262c36716833d078ce19ea6b58fbb83c2f8bee88b8685
5
5
  SHA512:
6
- metadata.gz: 2639ed20158afda2cc96dfeb16899f417d50180da548b4a45a0024c12119d0b9908649979fb9ab00287d41478f507eb6740ffda855aa238cd82755d774ca82de
7
- data.tar.gz: 6e6df86398ee4bde9ff9c54647dc5af95eb03e40001cf6117077afeecf20ecaed12f6e3f53b47bda1e2908094632c12e9d7faee3ee72c2422d7665016e583eff
6
+ metadata.gz: 027f57a717cb63fadeefd4a60213115a27ed51bb1eb3e6b58251690ed7c1d42335086ff4448b480296b77d395ba2e8718fa662e227394abfddaf80b19b769b74
7
+ data.tar.gz: f6aca254b4a43d6c60d5df7e6694b976de1e56fbb6d6585bd46fd17c0849820d76c81f25bbc872dc785576e05eeaaab5d0276a3f065b730988973c5073ace761
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Build Status](https://travis-ci.org/david942j/seccomp-tools.svg?branch=master)](https://travis-ci.org/david942j/seccomp-tools)
1
+ [![Build Status](https://github.com/david942j/seccomp-tools/workflows/build/badge.svg)](https://github.com/david942j/seccomp-tools/actions)
2
2
  [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=david942j/seccomp-tools)](https://dependabot.com)
3
3
  [![Code Climate](https://codeclimate.com/github/david942j/seccomp-tools/badges/gpa.svg)](https://codeclimate.com/github/david942j/seccomp-tools)
4
4
  [![Issue Count](https://codeclimate.com/github/david942j/seccomp-tools/badges/issue_count.svg)](https://codeclimate.com/github/david942j/seccomp-tools)
@@ -54,6 +54,7 @@ $ seccomp-tools --help
54
54
 
55
55
  $ seccomp-tools dump --help
56
56
  # dump - Automatically dump seccomp bpf from execution file(s).
57
+ # NOTE : This function is only available on Linux.
57
58
  #
58
59
  # Usage: seccomp-tools dump [exec] [options]
59
60
  # -c, --sh-exec <command> Executes the given command (via sh).
@@ -169,7 +170,7 @@ $ seccomp-tools asm
169
170
  # -f, --format FORMAT Output format. FORMAT can only be one of <inspect|raw|c_array|c_source|assembly>.
170
171
  # Default: inspect
171
172
  # -a, --arch ARCH Specify architecture.
172
- # Supported architectures are <amd64|i386>.
173
+ # Supported architectures are <aarch64|amd64|i386>.
173
174
  # Default: amd64
174
175
 
175
176
  # Input file for asm
@@ -267,7 +268,7 @@ $ seccomp-tools emu --help
267
268
  #
268
269
  # Usage: seccomp-tools emu [options] BPF_FILE [sys_nr [arg0 [arg1 ... arg5]]]
269
270
  # -a, --arch ARCH Specify architecture.
270
- # Supported architectures are <amd64|i386>.
271
+ # Supported architectures are <aarch64|amd64|i386>.
271
272
  # Default: amd64
272
273
  # -q, --[no-]quiet Run quietly, only show emulation result.
273
274
 
@@ -300,6 +301,13 @@ $ seccomp-tools emu spec/data/libseccomp.bpf write 0x3
300
301
 
301
302
  ![emu](https://github.com/david942j/seccomp-tools/blob/master/examples/emu-amigo.png?raw=true)
302
303
 
304
+ ## Architecture Supported
305
+
306
+ - [x] x86_64
307
+ - [x] x32
308
+ - [x] x86
309
+ - [x] arm64 (Thanks to @saagarjha!)
310
+
303
311
  ## Development
304
312
 
305
313
  I recommend to use [rbenv](https://github.com/rbenv/rbenv) for your Ruby environment.
data/ext/ptrace/ptrace.c CHANGED
@@ -1,7 +1,15 @@
1
+ // ptrace is only available on Linux, therefore let this file be an empty
2
+ // object when installing on other platforms.
3
+ #if __linux__
4
+
5
+ #include <assert.h>
1
6
  #include <errno.h>
7
+ #include <linux/elf.h>
2
8
  #include <linux/filter.h>
9
+ #include <stdint.h>
3
10
  #include <sys/ptrace.h>
4
11
  #include <sys/signal.h>
12
+ #include <sys/uio.h>
5
13
  #include <sys/wait.h>
6
14
 
7
15
  #include "ruby.h"
@@ -19,10 +27,53 @@ ptrace_peekdata(VALUE _mod, VALUE pid, VALUE addr, VALUE _data) {
19
27
  return LONG2NUM(val);
20
28
  }
21
29
 
30
+ // aarch64 doesn't support PTRACE_PEEKUSER, but it does support
31
+ // PTRACE_GETREGSET which is fairly similar. Since i386 and x86_64 support it
32
+ // too, just use that unconditionally to present the same API for the registers
33
+ // we care about.
22
34
  static VALUE
23
- ptrace_peekuser(VALUE _mod, VALUE pid, VALUE off, VALUE _data) {
24
- long val = ptrace(PTRACE_PEEKUSER, NUM2LONG(pid), NUM2LONG(off), NULL);
25
- return LONG2NUM(val);
35
+ ptrace_peekuser(VALUE _mod, VALUE pid, VALUE off, VALUE _data, VALUE bits) {
36
+ size_t offset = NUM2LONG(off);
37
+ // Unless your registers fill an entire page, an offset greater than this is
38
+ // probably wrong.
39
+ if (offset >= 4096) {
40
+ return LONG2NUM(-1);
41
+ }
42
+ size_t width = NUM2LONG(bits);
43
+ if (width != 32 && width != 64) {
44
+ return LONG2NUM(-1);
45
+ }
46
+ width /= 8;
47
+ union {
48
+ uint32_t val32;
49
+ uint64_t val64;
50
+ } val;
51
+ // Dynamically allocate a buffer to store registers-well, at least enough
52
+ // registers to reach the offset we want. Normally we'd want to use
53
+ // user_pt_regs or similar, but it's difficult to find it available in the
54
+ // the same header across different versions of Linux or libcs, or even with
55
+ // the same *name*, so this is the compromise.
56
+ size_t size = offset + width;
57
+ char *regs = malloc(size);
58
+ if (!regs) {
59
+ return LONG2NUM(-1);
60
+ }
61
+ struct iovec vec = { regs, size };
62
+ if (ptrace(PTRACE_GETREGSET, NUM2LONG(pid), NT_PRSTATUS, &vec) != -1 && vec.iov_len >= size) {
63
+ memcpy(&val, regs + offset, width);
64
+ } else {
65
+ free(regs);
66
+ return LONG2NUM(-1);
67
+ }
68
+ free(regs);
69
+ if (width == sizeof(val.val32)) {
70
+ return LONG2NUM(val.val32);
71
+ } else if (width == sizeof(val.val64)) {
72
+ return LONG2NUM(val.val64);
73
+ } else {
74
+ assert(!"Unreachable");
75
+ return LONG2NUM(-1);
76
+ }
26
77
  }
27
78
 
28
79
  static VALUE
@@ -107,7 +158,7 @@ void Init_ptrace(void) {
107
158
  /* get data */
108
159
  rb_define_module_function(mPtrace, "peekdata", ptrace_peekdata, 3);
109
160
  /* get registers */
110
- rb_define_module_function(mPtrace, "peekuser", ptrace_peekuser, 3);
161
+ rb_define_module_function(mPtrace, "peekuser", ptrace_peekuser, 4);
111
162
  /* set ptrace options */
112
163
  rb_define_module_function(mPtrace, "setoptions", ptrace_setoptions, 3);
113
164
  /* wait for syscall */
@@ -124,3 +175,4 @@ void Init_ptrace(void) {
124
175
  rb_define_module_function(mPtrace, "detach", ptrace_detach, 1);
125
176
  }
126
177
 
178
+ #endif /* __linux__ */
@@ -200,7 +200,7 @@ module SeccompTools
200
200
  token.fetch('goto') ||
201
201
  token.fetch('jmp') ||
202
202
  token.fetch('jump') ||
203
- raise(ArgumentError, 'Invalid jump alias: ' + token.cur.inspect)
203
+ raise(ArgumentError, "Invalid jump alias: #{token.cur.inspect}")
204
204
  target = token.fetch!(:goto)
205
205
  [:jmp_abs, target]
206
206
  end
@@ -254,7 +254,7 @@ module SeccompTools
254
254
  token.fetch('sys_number') ||
255
255
  token.fetch('arch') ||
256
256
  token.fetch('len') ||
257
- raise(ArgumentError, 'Invalid source: ' + token.cur.inspect)
257
+ raise(ArgumentError, "Invalid source: #{token.cur.inspect}")
258
258
  [:assign, dst, src]
259
259
  end
260
260
 
@@ -291,7 +291,7 @@ module SeccompTools
291
291
 
292
292
  def invalid(line, extra_msg = nil)
293
293
  message = "Invalid instruction at line #{line + 1}: #{@input[line].inspect}"
294
- message += "\n" + 'Error: ' + extra_msg if extra_msg
294
+ message += "\nError: #{extra_msg}" if extra_msg
295
295
  raise ArgumentError, message
296
296
  end
297
297
  end
@@ -34,10 +34,10 @@ module SeccompTools
34
34
  def initialize(raw, arch, line)
35
35
  if raw.is_a?(String)
36
36
  io = ::StringIO.new(raw)
37
- @code = io.read(2).unpack('S').first
37
+ @code = io.read(2).unpack1('S')
38
38
  @jt = io.read(1).ord
39
39
  @jf = io.read(1).ord
40
- @k = io.read(4).unpack('L').first
40
+ @k = io.read(4).unpack1('L')
41
41
  else
42
42
  @code = raw[:code]
43
43
  @jt = raw[:jt]
@@ -10,7 +10,7 @@ module SeccompTools
10
10
  # Summary of this command.
11
11
  SUMMARY = 'Seccomp bpf assembler.'
12
12
  # Usage of this command.
13
- USAGE = ('asm - ' + SUMMARY + "\n\n" + 'Usage: seccomp-tools asm IN_FILE [options]').freeze
13
+ USAGE = "asm - #{SUMMARY}\n\nUsage: seccomp-tools asm IN_FILE [options]"
14
14
 
15
15
  def initialize(*)
16
16
  super
@@ -47,7 +47,7 @@ module SeccompTools
47
47
  res = SeccompTools::Asm.asm(input, arch: option[:arch])
48
48
  output do
49
49
  case option[:format]
50
- when :inspect then res.inspect + "\n"
50
+ when :inspect then "#{res.inspect}\n"
51
51
  when :raw then res
52
52
  when :c_array, :carray then "unsigned char bpf[] = {#{res.bytes.join(',')}};\n"
53
53
  when :c_source then SeccompTools::Util.template('asm.c').sub('<TO_BE_REPLACED>', res.bytes.join(','))
@@ -39,7 +39,7 @@ module SeccompTools
39
39
  # @return [String]
40
40
  # String read from file.
41
41
  def input
42
- option[:ifile] == '-' ? STDIN.read.force_encoding('ascii-8bit') : IO.binread(option[:ifile])
42
+ option[:ifile] == '-' ? $stdin.read.force_encoding('ascii-8bit') : IO.binread(option[:ifile])
43
43
  end
44
44
 
45
45
  # Write data to stdout or file(s).
@@ -10,7 +10,7 @@ module SeccompTools
10
10
  # Summary of this command.
11
11
  SUMMARY = 'Disassemble seccomp bpf.'
12
12
  # Usage of this command.
13
- USAGE = ('disasm - ' + SUMMARY + "\n\n" + 'Usage: seccomp-tools disasm BPF_FILE [options]').freeze
13
+ USAGE = "disasm - #{SUMMARY}\n\nUsage: seccomp-tools disasm BPF_FILE [options]"
14
14
 
15
15
  # Define option parser.
16
16
  # @return [OptionParser]
@@ -14,7 +14,8 @@ module SeccompTools
14
14
  # Summary of this command.
15
15
  SUMMARY = 'Automatically dump seccomp bpf from execution file(s).'
16
16
  # Usage of this command.
17
- USAGE = ('dump - ' + SUMMARY + "\n\n" + 'Usage: seccomp-tools dump [exec] [options]').freeze
17
+ USAGE = "dump - #{SUMMARY}\nNOTE : This function is only available on Linux." \
18
+ "\n\nUsage: seccomp-tools dump [exec] [options]"
18
19
 
19
20
  def initialize(*)
20
21
  super
@@ -64,11 +65,12 @@ module SeccompTools
64
65
  # Handle options.
65
66
  # @return [void]
66
67
  def handle
68
+ return Logger.error('Dump is only available on Linux.') unless Dumper::SUPPORTED
67
69
  return unless super
68
70
 
69
71
  block = lambda do |bpf, arch|
70
72
  case option[:format]
71
- when :inspect then output { '"' + bpf.bytes.map { |b| format('\\x%02X', b) }.join + "\"\n" }
73
+ when :inspect then output { "\"#{bpf.bytes.map { |b| format('\\x%02X', b) }.join}\"\n" }
72
74
  when :raw then output { bpf }
73
75
  when :disasm then output { SeccompTools::Disasm.disasm(bpf, arch: arch) }
74
76
  end
@@ -15,10 +15,7 @@ module SeccompTools
15
15
  # Summary of this command.
16
16
  SUMMARY = 'Emulate seccomp rules.'
17
17
  # Usage of this command.
18
- USAGE = ('emu - ' +
19
- SUMMARY +
20
- "\n\n" \
21
- 'Usage: seccomp-tools emu [options] BPF_FILE [sys_nr [arg0 [arg1 ... arg5]]]').freeze
18
+ USAGE = "emu - #{SUMMARY}\n\nUsage: seccomp-tools emu [options] BPF_FILE [sys_nr [arg0 [arg1 ... arg5]]]"
22
19
 
23
20
  def initialize(*)
24
21
  super
@@ -59,6 +59,8 @@ module SeccompTools
59
59
  KILL: 0x00000000, # alias of KILL_THREAD
60
60
  TRAP: 0x00030000,
61
61
  ERRNO: 0x00050000,
62
+ USER_NOTIF: 0x7fc00000,
63
+ LOG: 0x7ffc0000,
62
64
  TRACE: 0x7ff00000,
63
65
  ALLOW: 0x7fff0000
64
66
  }.freeze
@@ -120,17 +122,28 @@ module SeccompTools
120
122
 
121
123
  const_set(cons, instance_eval(IO.read(filename)))
122
124
  end
125
+
126
+ def load_args
127
+ hash = instance_eval(IO.read(File.join(__dir__, 'consts', 'sys_arg.rb')))
128
+ Hash.new do |_h, k|
129
+ next hash[k] if hash[k]
130
+ next hash[k.to_s[4..-1].to_sym] if k.to_s.start_with?('x32_')
131
+
132
+ nil
133
+ end
134
+ end
123
135
  end
124
136
 
125
137
  # The argument names of all syscalls.
126
- SYS_ARG = instance_eval(IO.read(File.join(__dir__, 'consts', 'sys_arg.rb'))).freeze
138
+ SYS_ARG = Syscall.load_args.freeze
127
139
 
128
140
  # Constants from https://github.com/torvalds/linux/blob/master/include/uapi/linux/audit.h.
129
141
  module Audit
130
142
  # AUDIT_ARCH_*
131
143
  ARCH = {
132
144
  'ARCH_X86_64' => 0xc000003e,
133
- 'ARCH_I386' => 0x40000003
145
+ 'ARCH_I386' => 0x40000003,
146
+ 'ARCH_AARCH64' => 0xc00000b7
134
147
  }.freeze
135
148
  end
136
149
  end
@@ -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,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ X32_MODE_BIT = 0x40000000
3
4
  {
4
5
  read: 0,
5
6
  write: 1,
@@ -18,7 +19,9 @@
18
19
  rt_sigprocmask: 14,
19
20
  rt_sigreturn: 15,
20
21
  ioctl: 16,
22
+ pread: 17,
21
23
  pread64: 17,
24
+ pwrite: 18,
22
25
  pwrite64: 18,
23
26
  readv: 19,
24
27
  writev: 20,
@@ -334,4 +337,4 @@
334
337
  pkey_alloc: 330,
335
338
  pkey_free: 331,
336
339
  statx: 332
337
- }
340
+ }.tap { |h| h.keys.each { |k| h["x32_#{k}".to_sym] = h[k] | X32_MODE_BIT } } # rubocop:disable Style/HashEachMethods
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  {
4
- setup: 0,
4
+ restart_syscall: 0,
5
5
  exit: 1,
6
6
  fork: 2,
7
7
  read: 3,
@@ -259,14 +259,14 @@
259
259
  remap_file_pages: 257,
260
260
  set_tid_address: 258,
261
261
  timer_create: 259,
262
- timer_settime: (259 + 1),
263
- timer_gettime: (259 + 2),
264
- timer_getoverrun: (259 + 3),
265
- timer_delete: (259 + 4),
266
- clock_settime: (259 + 5),
267
- clock_gettime: (259 + 6),
268
- clock_getres: (259 + 7),
269
- 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,
270
270
  statfs64: 268,
271
271
  fstatfs64: 269,
272
272
  tgkill: 270,
@@ -277,11 +277,11 @@
277
277
  get_mempolicy: 275,
278
278
  set_mempolicy: 276,
279
279
  mq_open: 277,
280
- mq_unlink: (277 + 1),
281
- mq_timedsend: (277 + 2),
282
- mq_timedreceive: (277 + 3),
283
- mq_notify: (277 + 4),
284
- mq_getsetattr: (277 + 5),
280
+ mq_unlink: 278,
281
+ mq_timedsend: 279,
282
+ mq_timedreceive: 280,
283
+ mq_notify: 281,
284
+ mq_getsetattr: 282,
285
285
  sys_kexec_load: 283,
286
286
  waitid: 284,
287
287
  add_key: 286,
@@ -30,9 +30,10 @@ module SeccompTools
30
30
  code.contexts = ctxs
31
31
  code.disasm
32
32
  end.join("\n")
33
- <<-EOS + dis + "\n"
33
+ <<-EOS
34
34
  line CODE JT JF K
35
35
  =================================
36
+ #{dis}
36
37
  EOS
37
38
  end
38
39
 
@@ -1,13 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'os'
4
+
3
5
  require 'seccomp-tools/logger'
4
- require 'seccomp-tools/ptrace'
6
+ require 'seccomp-tools/ptrace' if OS.linux?
5
7
  require 'seccomp-tools/syscall'
6
8
 
7
9
  module SeccompTools
8
10
  # Dump seccomp-bpf using ptrace of binary.
9
- # Currently only support x86_64.
11
+ # Currently only support x86_64 and aarch64.
10
12
  module Dumper
13
+ # Whether the dumper is supported.
14
+ # Dumper works based on ptrace, so we need the platform be Linux.
15
+ SUPPORTED = OS.linux?
16
+
11
17
  module_function
12
18
 
13
19
  # Main bpf dump function.
@@ -35,6 +41,8 @@ module SeccompTools
35
41
  # @todo
36
42
  # +timeout+ option.
37
43
  def dump(*args, limit: 1, &block)
44
+ return [] unless SUPPORTED
45
+
38
46
  pid = fork { handle_child(*args) }
39
47
  Handler.new(pid).handle(limit, &block)
40
48
  end
@@ -164,6 +172,8 @@ module SeccompTools
164
172
  # dump_by_pid(pid2, 1) { |c| c[0, 10] }
165
173
  # #=> [" \x00\x00\x00\x00\x00\x00\x00\x15\x00"]
166
174
  def dump_by_pid(pid, limit, &block)
175
+ return [] unless SUPPORTED
176
+
167
177
  collect = []
168
178
  Ptrace.attach_and_wait(pid)
169
179
  begin
@@ -58,10 +58,11 @@ module SeccompTools
58
58
  end
59
59
 
60
60
  def audit(arch)
61
- type = case arch
62
- when :amd64 then 'ARCH_X86_64'
63
- when :i386 then 'ARCH_I386'
64
- end
61
+ type = {
62
+ amd64: 'ARCH_X86_64',
63
+ i386: 'ARCH_I386',
64
+ aarch64: 'ARCH_AARCH64'
65
+ }[arch]
65
66
  Const::Audit::ARCH[type]
66
67
  end
67
68
 
@@ -62,7 +62,7 @@ module SeccompTools
62
62
 
63
63
  case op
64
64
  when :lsh, :rsh then src.to_s
65
- else '0x' + src.to_s(16)
65
+ else "0x#{src.to_s(16)}"
66
66
  end
67
67
  end
68
68
 
@@ -16,9 +16,9 @@ module SeccompTools
16
16
  # otherwise => if () goto jt; else goto jf;
17
17
  return '/* no-op */' if jt.zero? && jf.zero?
18
18
  return goto(jt) if jt == jf
19
- return if_str(true) + goto(jf) if jt.zero?
19
+ return if_str(neg: true) + goto(jf) if jt.zero?
20
20
 
21
- if_str + goto(jt) + (jf.zero? ? '' : ' else ' + goto(jf))
21
+ if_str + goto(jt) + (jf.zero? ? '' : " else #{goto(jf)}")
22
22
  end
23
23
 
24
24
  # See {Instruction::Base#symbolize}.
@@ -64,14 +64,19 @@ module SeccompTools
64
64
  a = a[0]
65
65
  return k.to_s unless a.data?
66
66
 
67
- hex = '0x' + k.to_s(16)
67
+ hex = "0x#{k.to_s(16)}"
68
68
  case a.val
69
- when 0 then Util.colorize(Const::Syscall.const_get(arch.upcase.to_sym).invert[k] || hex, t: :syscall)
69
+ # interpret as syscalls only if it's an equality test
70
+ when 0 then Util.colorize(jop == :== ? sysname_by_k || hex : hex, t: :syscall)
70
71
  when 4 then Util.colorize(Const::Audit::ARCH.invert[k] || hex, t: :arch)
71
72
  else hex
72
73
  end
73
74
  end
74
75
 
76
+ def sysname_by_k
77
+ Const::Syscall.const_get(arch.upcase.to_sym).invert[k]
78
+ end
79
+
75
80
  def src
76
81
  SRC.invert[code & 8] == :x ? :x : k
77
82
  end
@@ -84,15 +89,15 @@ module SeccompTools
84
89
  line + off + 1
85
90
  end
86
91
 
87
- def if_str(neg = false)
92
+ def if_str(neg: false)
88
93
  return "if (A #{jop} #{src_str}) " unless neg
89
94
  return "if (!(A & #{src_str})) " if jop == :&
90
95
 
91
- op = case jop
92
- when :>= then :<
93
- when :> then :<=
94
- when :== then :!=
95
- end
96
+ op = {
97
+ :>= => :<,
98
+ :> => :<=,
99
+ :== => :!=
100
+ }[jop]
96
101
  "if (A #{op} #{src_str}) "
97
102
  end
98
103
  end
@@ -10,7 +10,7 @@ module SeccompTools
10
10
  class LD < Base
11
11
  # Decompile instruction.
12
12
  def decompile
13
- ret = reg + ' = '
13
+ ret = "#{reg} = "
14
14
  _, _reg, type = symbolize
15
15
  return ret + type[:val].to_s if type[:rel] == :immi
16
16
  return ret + "mem[#{type[:val]}]" if type[:rel] == :mem
@@ -88,7 +88,7 @@ module SeccompTools
88
88
 
89
89
  comment = "# #{sys}(#{args.join(', ')})"
90
90
  arg_name = Util.colorize(args[idx / 2], t: :args)
91
- (idx.even? ? arg_name : "#{arg_name} >> 32") + ' ' + Util.colorize(comment, t: :gray)
91
+ "#{idx.even? ? arg_name : "#{arg_name} >> 32"} #{Util.colorize(comment, t: :gray)}"
92
92
  end
93
93
  end
94
94
  end
@@ -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,7 +11,8 @@ 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 }
13
16
  }.freeze
14
17
 
15
18
  # @return [Integer] Process id.
@@ -60,10 +63,11 @@ module SeccompTools
60
63
  # Architecture of this syscall.
61
64
  def arch
62
65
  @arch ||= File.open("/proc/#{pid}/exe", 'rb') do |f|
63
- f.pos = 4
66
+ f.pos = 18
64
67
  case f.read(1).ord
65
- when 1 then :i386
66
- when 2 then :amd64
68
+ when 3 then :i386
69
+ when 62 then :amd64
70
+ when 183 then :aarch64
67
71
  end
68
72
  end
69
73
  end
@@ -71,14 +75,15 @@ module SeccompTools
71
75
  private
72
76
 
73
77
  def bits
74
- case arch
75
- when :i386 then 32
76
- when :amd64 then 64
77
- end
78
+ {
79
+ i386: 32,
80
+ amd64: 64,
81
+ aarch64: 64
82
+ }[arch]
78
83
  end
79
84
 
80
85
  def peek(offset)
81
- Ptrace.peekuser(pid, offset, 0)
86
+ Ptrace.peekuser(pid, offset, 0, bits)
82
87
  end
83
88
  end
84
89
  end
@@ -20,6 +20,7 @@ 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
23
24
  else :unknown
24
25
  end
25
26
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module SeccompTools
4
4
  # Gem version.
5
- VERSION = '1.4.0'
5
+ VERSION = '1.5.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.5.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: 2021-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -58,28 +58,34 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.79'
61
+ version: '1.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.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.17'
76
+ - - "<"
77
+ - !ruby/object:Gem::Version
78
+ version: '0.18'
76
79
  type: :development
77
80
  prerelease: false
78
81
  version_requirements: !ruby/object:Gem::Requirement
79
82
  requirements:
80
83
  - - "~>"
81
84
  - !ruby/object:Gem::Version
82
- version: 0.17.0
85
+ version: '0.17'
86
+ - - "<"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.18'
83
89
  - !ruby/object:Gem::Dependency
84
90
  name: yard
85
91
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +100,26 @@ dependencies:
94
100
  - - "~>"
95
101
  - !ruby/object:Gem::Version
96
102
  version: '0.9'
103
+ - !ruby/object:Gem::Dependency
104
+ name: os
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.1'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 1.1.1
113
+ type: :runtime
114
+ prerelease: false
115
+ version_requirements: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '1.1'
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 1.1.1
97
123
  description: |
98
124
  Provide useful tools to analyze seccomp rules.
99
125
  Visit https://github.com/david942j/seccomp-tools for more details.
@@ -122,6 +148,7 @@ files:
122
148
  - lib/seccomp-tools/cli/emu.rb
123
149
  - lib/seccomp-tools/const.rb
124
150
  - lib/seccomp-tools/consts/sys_arg.rb
151
+ - lib/seccomp-tools/consts/sys_nr/aarch64.rb
125
152
  - lib/seccomp-tools/consts/sys_nr/amd64.rb
126
153
  - lib/seccomp-tools/consts/sys_nr/i386.rb
127
154
  - lib/seccomp-tools/disasm/context.rb
@@ -168,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
195
  - !ruby/object:Gem::Version
169
196
  version: '0'
170
197
  requirements: []
171
- rubygems_version: 3.0.3
198
+ rubygems_version: 3.1.4
172
199
  signing_key:
173
200
  specification_version: 4
174
201
  summary: seccomp-tools