seccomp-tools 1.6.2 → 1.7.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +153 -0
  3. data/README.md +263 -42
  4. data/completions/_seccomp-tools +83 -0
  5. data/completions/seccomp-tools.bash +59 -0
  6. data/completions/seccomp-tools.fish +52 -0
  7. data/ext/ptrace/ptrace.c +2 -2
  8. data/lib/seccomp-tools/asm/asm.rb +9 -4
  9. data/lib/seccomp-tools/asm/compiler.rb +32 -2
  10. data/lib/seccomp-tools/asm/sasm.tab.rb +27 -19
  11. data/lib/seccomp-tools/asm/sasm.y +15 -7
  12. data/lib/seccomp-tools/asm/scalar.rb +50 -7
  13. data/lib/seccomp-tools/asm/scanner.rb +33 -1
  14. data/lib/seccomp-tools/asm/statement.rb +14 -5
  15. data/lib/seccomp-tools/asm/token.rb +19 -1
  16. data/lib/seccomp-tools/audit/catalog.rb +66 -0
  17. data/lib/seccomp-tools/audit/checks/arch_unchecked.rb +41 -0
  18. data/lib/seccomp-tools/audit/checks/dangerous_allow.rb +34 -0
  19. data/lib/seccomp-tools/audit/checks/orw_chain.rb +41 -0
  20. data/lib/seccomp-tools/audit/checks/permissive_default.rb +29 -0
  21. data/lib/seccomp-tools/audit/checks/syscall_alt_gap.rb +44 -0
  22. data/lib/seccomp-tools/audit/checks/x32_guard.rb +46 -0
  23. data/lib/seccomp-tools/audit/checks.rb +42 -0
  24. data/lib/seccomp-tools/audit/finding.rb +25 -0
  25. data/lib/seccomp-tools/audit/policy.rb +126 -0
  26. data/lib/seccomp-tools/audit/report.rb +98 -0
  27. data/lib/seccomp-tools/audit.rb +48 -0
  28. data/lib/seccomp-tools/bpf.rb +27 -17
  29. data/lib/seccomp-tools/cli/asm.rb +6 -2
  30. data/lib/seccomp-tools/cli/audit.rb +86 -0
  31. data/lib/seccomp-tools/cli/base.rb +51 -8
  32. data/lib/seccomp-tools/cli/cli.rb +9 -3
  33. data/lib/seccomp-tools/cli/completion.rb +40 -0
  34. data/lib/seccomp-tools/cli/disasm.rb +9 -5
  35. data/lib/seccomp-tools/cli/dump.rb +37 -52
  36. data/lib/seccomp-tools/cli/dumpable.rb +79 -0
  37. data/lib/seccomp-tools/cli/emu.rb +20 -5
  38. data/lib/seccomp-tools/cli/explain.rb +51 -0
  39. data/lib/seccomp-tools/cli/filter_input.rb +130 -0
  40. data/lib/seccomp-tools/const.rb +98 -15
  41. data/lib/seccomp-tools/consts/sys_nr/riscv64.rb +332 -0
  42. data/lib/seccomp-tools/disasm/disasm.rb +30 -12
  43. data/lib/seccomp-tools/dumper.rb +65 -33
  44. data/lib/seccomp-tools/emulator.rb +40 -15
  45. data/lib/seccomp-tools/error.rb +4 -2
  46. data/lib/seccomp-tools/explain/analysis.rb +67 -0
  47. data/lib/seccomp-tools/explain/path_facts.rb +110 -0
  48. data/lib/seccomp-tools/explain/qword.rb +204 -0
  49. data/lib/seccomp-tools/explain/renderer.rb +128 -0
  50. data/lib/seccomp-tools/explain/summary.rb +218 -0
  51. data/lib/seccomp-tools/explain/verdict.rb +44 -0
  52. data/lib/seccomp-tools/explain.rb +38 -0
  53. data/lib/seccomp-tools/instruction/alu.rb +14 -9
  54. data/lib/seccomp-tools/instruction/base.rb +39 -10
  55. data/lib/seccomp-tools/instruction/jmp.rb +50 -23
  56. data/lib/seccomp-tools/instruction/ld.rb +46 -21
  57. data/lib/seccomp-tools/instruction/ldx.rb +4 -3
  58. data/lib/seccomp-tools/instruction/misc.rb +11 -9
  59. data/lib/seccomp-tools/instruction/ret.rb +12 -6
  60. data/lib/seccomp-tools/instruction/st.rb +15 -6
  61. data/lib/seccomp-tools/instruction/stx.rb +4 -3
  62. data/lib/seccomp-tools/logger.rb +14 -1
  63. data/lib/seccomp-tools/symbolic/constraint.rb +80 -0
  64. data/lib/seccomp-tools/symbolic/executor.rb +210 -0
  65. data/lib/seccomp-tools/symbolic/expr.rb +185 -0
  66. data/lib/seccomp-tools/symbolic/state.rb +82 -0
  67. data/lib/seccomp-tools/syscall.rb +72 -20
  68. data/lib/seccomp-tools/util.rb +70 -11
  69. data/lib/seccomp-tools/version.rb +1 -1
  70. data/lib/seccomp-tools.rb +10 -1
  71. metadata +36 -4
  72. data/lib/seccomp-tools/disasm/context.rb +0 -171
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e367e58696b5e8ff43054439401688981bcc960c0f80882384054245f21efbe4
4
- data.tar.gz: 3af03e40f20244cf2bdbc82254a514d84c6792d87bd167305c4b0edd9a356f35
3
+ metadata.gz: 74e6aff6030647eb1f380b641cfe55b58717a22c3e5dc2a0187e6da9b74263e3
4
+ data.tar.gz: 2c0a322b81f7d4b950686dc5c72d565cad5e3a278f47a442d7271c0ac4e03417
5
5
  SHA512:
6
- metadata.gz: 5d8542e0a5330c40418947ed864a32fb9b125ed6b25aead0faadcb7743cae4c3b03a17a7dfaf41a90e0585e7ffb407e2af00cbc931e9e3c2334f0f176cf368c7
7
- data.tar.gz: c08c293b669e59d253daec6351f4b43a4ae3d34fe9b25bc9663e5a3f21361f90b15d578cf0c4be1e468b50e8ceb7b3b6e36117eb7aa7bea66dd38fa1cc8680b5
6
+ metadata.gz: 2a8793275d9dd37fc1ed1dc0abc67a07c9aca17f9aa4b03f26c2a0ce31b27861b64f0e85608588b47841a644ae98cb4b4c34460eef8a37c5ca3a6fa0664fbb01
7
+ data.tar.gz: f7ab61c28a821022989c3d1ef31ab9fb966e132d6211f861339d64bf9cdffe451f970d932a4d47a890220914bf8451a0fb35afdaca191391a6b0bea4d26f9227
data/CHANGELOG.md ADDED
@@ -0,0 +1,153 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.7.0] - 2026-08-01
11
+
12
+ ### Added
13
+ - `completion` command: print a shell completion script for bash, zsh or fish (e.g. `eval "$(seccomp-tools completion bash)"`).
14
+ - `explain` command: summarize a whole filter as a per-action policy (which syscalls end in ALLOW/KILL/ERRNO, and under what argument constraints).
15
+ - `audit` command: scan a filter for weaknesses and escape routes (missing architecture or x32 guard, permissive default, equivalent-syscall gaps, an open/read/write chain, dangerous syscalls reachable as ALLOW), with a `--format json` output.
16
+ - RISC-V 64 (`riscv64`) architecture support across dump, disasm, asm and emu.
17
+ - `dump --timeout SEC` to bound how long a traced program runs.
18
+ - `dump` now handles `SECCOMP_MODE_STRICT`, emitting the equivalent filter (strict mode installs no BPF of its own).
19
+
20
+ ### Changed
21
+ - disasm, emu and asm now share a symbolic BPF execution engine; disasm names arguments by the architecture inferred from the filter rather than the one declared on the command line.
22
+ - `dump --pid` detects the target process's architecture (from its ELF header) instead of assuming the host's, so syscalls of a process built for another architecture are labelled correctly.
23
+ - `dump`'s `-c`/`--sh-exec` now takes precedence over a positional executable.
24
+ - `dump` warns when it finds no seccomp filter instead of printing nothing.
25
+ - Commands that need an architecture now fail with a clear message when the host architecture cannot be detected and no `--arch` was given, instead of erroring deep inside a syscall-table lookup.
26
+ - Colorized syscall names, gave warnings and info messages a color, and wrapped audit findings to 120 columns.
27
+
28
+ ### Fixed
29
+ - Corrected 64-bit argument word order on big-endian (s390x) targets.
30
+ - Fixed the disassembly of seccomp return actions via a shared action-label decoder.
31
+ - The emulator now models division by zero as the kernel does (aborting the program with a kill) instead of raising.
32
+ - Fixed a Bundler error on Ruby head.
33
+
34
+ ## [1.6.2] - 2025-11-23
35
+
36
+ ### Added
37
+ - Ruby 3.4 support.
38
+ - `-i`/`--ip` option to set the instruction pointer in emulation mode.
39
+
40
+ ### Changed
41
+ - Raised the minimum Ruby version to 3.1 (dropped 3.0).
42
+ - Declared `logger` as an explicit dependency (it is no longer a default gem).
43
+
44
+ ### Fixed
45
+ - Bundled the license file and a missing runtime dependency in the gem.
46
+
47
+ ## [1.6.1] - 2023-12-25
48
+
49
+ ### Fixed
50
+ - Stopped raising an error on a long direct jump.
51
+ - Fixed wrong decompilation when the compiler optimized two branches to the same jump target.
52
+
53
+ ## [1.6.0] - 2023-09-19
54
+
55
+ ### Added
56
+ - Rewrote the `asm` assembler on a yacc (racc) based grammar, supporting a more flexible and intuitive syntax.
57
+ - `disasm --asm-able` to emit output that is valid input for `asm`.
58
+ - `disasm --no-bpf` to hide the raw BPF bytes.
59
+ - `<arch>.<syscall>` syntax in disasm and asm.
60
+ - Support for `!` (bang) in `if` conditions.
61
+ - Dumping seccomp filters on s390x.
62
+
63
+ ### Changed
64
+ - Raise an error when a jump distance exceeds 255.
65
+ - Sped up the assembler's scanner.
66
+
67
+ ## [1.5.0] - 2021-03-07
68
+
69
+ ### Added
70
+ - x32 syscall support.
71
+ - Dumping seccomp filters on aarch64.
72
+ - Additional seccomp return actions.
73
+ - Syscall-name aliases matching `ausyscall`.
74
+
75
+ ### Changed
76
+ - Skip the (Linux-only) dump functionality gracefully when installing on macOS.
77
+ - Migrated CI from Travis to GitHub Actions.
78
+
79
+ ## [1.4.0] - 2020-02-16
80
+
81
+ ### Added
82
+ - Dumping seccomp filters from an existing process (`dump --pid`).
83
+ - `A = -A` (negate) assembler syntax.
84
+ - An internal logger.
85
+
86
+ ### Changed
87
+ - Upgraded dependencies and dropped Ruby 2.3.
88
+
89
+ ## [1.3.0] - 2019-06-23
90
+
91
+ ### Added
92
+ - Display of syscall arguments in the disassembly.
93
+ - Support a syscall name (not just a number) in the emulator.
94
+ - `c_source` and x86 `assembly` output formats for `asm`.
95
+ - Assembler support for `mem[]`, `len`, and absolute jumps.
96
+ - `sys_seccomp` on i386.
97
+
98
+ ### Fixed
99
+ - A wrong regular expression in the tokenizer, and several reported bugs (#53, #54, #55).
100
+
101
+ ### Changed
102
+ - Dropped an end-of-life Ruby version (2.2).
103
+
104
+ ## [1.2.0] - 2018-04-05
105
+
106
+ ### Added
107
+ - `KILL_PROCESS` return action.
108
+ - `ARCH_X86_64` in the assembler.
109
+ - The `seccomp` syscall introduced in Linux 3.17.
110
+
111
+ ## [1.1.1] - 2017-12-01
112
+
113
+ ### Added
114
+ - Show `errno` in the disassembly of an ERRNO return.
115
+ - Assembler support for `st`/`stx`.
116
+
117
+ ### Fixed
118
+ - `lsh`/`rsh` in the assembler.
119
+
120
+ ### Changed
121
+ - More meaningful error messages.
122
+
123
+ ## [1.1.0] - 2017-09-29
124
+
125
+ ### Added
126
+ - `asm` command: a seccomp BPF assembler.
127
+
128
+ ## [1.0.0] - 2017-06-10
129
+
130
+ ### Added
131
+ - `emu` command: emulate seccomp rules against a hypothetical syscall.
132
+
133
+ ### Fixed
134
+ - Branch handling in the disassembler.
135
+
136
+ ## [0.1.0] - 2017-06-08
137
+
138
+ ### Added
139
+ - Initial release: the `dump` and `disasm` commands, ptrace-based dumping with `--limit` and `--output`, and i386 support.
140
+
141
+ [Unreleased]: https://github.com/david942j/seccomp-tools/compare/v1.7.0...HEAD
142
+ [1.7.0]: https://github.com/david942j/seccomp-tools/compare/v1.6.2...v1.7.0
143
+ [1.6.2]: https://github.com/david942j/seccomp-tools/compare/v1.6.1...v1.6.2
144
+ [1.6.1]: https://github.com/david942j/seccomp-tools/compare/v1.6.0...v1.6.1
145
+ [1.6.0]: https://github.com/david942j/seccomp-tools/compare/v1.5.0...v1.6.0
146
+ [1.5.0]: https://github.com/david942j/seccomp-tools/compare/v1.4.0...v1.5.0
147
+ [1.4.0]: https://github.com/david942j/seccomp-tools/compare/1.3.0...v1.4.0
148
+ [1.3.0]: https://github.com/david942j/seccomp-tools/compare/v1.2.0...1.3.0
149
+ [1.2.0]: https://github.com/david942j/seccomp-tools/compare/v1.1.1...v1.2.0
150
+ [1.1.1]: https://github.com/david942j/seccomp-tools/compare/v1.1.0...v1.1.1
151
+ [1.1.0]: https://github.com/david942j/seccomp-tools/compare/v1.0.0...v1.1.0
152
+ [1.0.0]: https://github.com/david942j/seccomp-tools/compare/v0.1.0...v1.0.0
153
+ [0.1.0]: https://github.com/david942j/seccomp-tools/releases/tag/v0.1.0
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ [![Downloads](https://img.shields.io/gem/dt/seccomp-tools)](https://rubygems.org/gems/seccomp-tools)
2
+
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/seccomp-tools.svg)](https://badge.fury.io/rb/seccomp-tools)
1
5
  [![Build Status](https://github.com/david942j/seccomp-tools/workflows/build/badge.svg)](https://github.com/david942j/seccomp-tools/actions)
2
6
  [![Maintainability](https://qlty.sh/gh/david942j/projects/seccomp-tools/maintainability.svg)](https://qlty.sh/gh/david942j/projects/seccomp-tools)
3
7
  [![Code Coverage](https://qlty.sh/gh/david942j/projects/seccomp-tools/coverage.svg)](https://qlty.sh/gh/david942j/projects/seccomp-tools)
@@ -6,20 +10,22 @@
6
10
  [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](http://choosealicense.com/licenses/mit/)
7
11
 
8
12
  # Seccomp Tools
9
- Provide powerful tools for seccomp analysis.
13
+ Powerful tools for seccomp analysis.
10
14
 
11
- This project targets to (but is not limited to) analyze seccomp sandbox in CTF pwn challenges.
12
- Some features might be CTF-specific, but also useful for analyzing seccomp of real cases.
15
+ This project is aimed primarily (but not exclusively) at analyzing seccomp sandboxes in CTF pwn challenges.
16
+ Some features are CTF-specific, but they're just as useful for analyzing real-world seccomp filters.
13
17
 
14
18
  ## Features
15
- * Dump - Automatically dumps seccomp BPF from execution file(s).
16
- * Disasm - Converts seccomp BPF to a human readable format.
19
+ * Dump - Automatically dumps seccomp BPF from executables.
20
+ * Disasm - Converts seccomp BPF to a human-readable format.
17
21
  - With simple decompilation.
18
22
  - With syscall names and arguments whenever possible.
19
23
  - Colorful!
20
- * Asm - Makes writing seccomp rules similar to writing codes.
24
+ * Asm - Makes writing seccomp rules as easy as writing code.
21
25
  * Emu - Emulates seccomp rules.
22
- * Supports multi-architecture.
26
+ * Explain - Summarizes a filter as a per-action policy (which syscalls are allowed/killed, and when).
27
+ * Audit - Scans a filter for weaknesses and escape routes (missing arch/x32 guards, dangerous syscalls, ...).
28
+ * Multi-architecture support.
23
29
 
24
30
  ## Installation
25
31
 
@@ -28,11 +34,11 @@ Available on RubyGems.org!
28
34
  $ gem install seccomp-tools
29
35
  ```
30
36
 
31
- If you failed when compiling, try:
37
+ If compilation fails, try:
32
38
  ```
33
39
  sudo apt install gcc ruby-dev make
34
40
  ```
35
- and install seccomp-tools again.
41
+ then install seccomp-tools again.
36
42
 
37
43
  ## Command Line Interface
38
44
 
@@ -45,40 +51,44 @@ $ seccomp-tools --help
45
51
  # List of commands:
46
52
  #
47
53
  # asm Seccomp bpf assembler.
54
+ # audit Assess a seccomp filter for weaknesses and escape routes.
55
+ # completion Print a shell completion script.
48
56
  # disasm Disassemble seccomp bpf.
49
- # dump Automatically dump seccomp bpf from execution file(s).
57
+ # dump Automatically dump seccomp bpf from executable(s).
50
58
  # emu Emulate seccomp rules.
59
+ # explain Summarize a seccomp filter as a per-action policy.
51
60
  #
52
61
  # See 'seccomp-tools <command> --help' to read about a specific subcommand.
53
62
 
54
63
  $ seccomp-tools dump --help
55
- # dump - Automatically dump seccomp bpf from execution file(s).
56
- # NOTE : This function is only available on Linux.
64
+ # dump - Automatically dump seccomp bpf from executable(s).
65
+ # NOTE: This command is only available on Linux.
57
66
  #
58
- # Usage: seccomp-tools dump [exec] [options]
59
- # -c, --sh-exec <command> Executes the given command (via sh).
60
- # Use this option if want to pass arguments or do pipe things to the execution file.
61
- # e.g. use `-c "./bin > /dev/null"` to dump seccomp without being mixed with stdout.
67
+ # Usage: seccomp-tools dump [EXEC] [options]
68
+ # -c, --sh-exec <command> Executes the given command (via sh) and dumps its seccomp.
69
+ # Use this to pass arguments or pipe things to the executable.
70
+ # e.g. use `-c "./bin > /dev/null"` to keep the program output out of the result.
71
+ # Takes precedence over the positional argument.
72
+ # -l, --limit LIMIT Dump only the first LIMIT installed filters.
73
+ # Only meaningful when the input is an executable or --pid. Default: 1
74
+ # An executable is killed once it reaches LIMIT.
75
+ # -p, --pid PID Dump the seccomp filters installed on an existing process.
76
+ # You must have CAP_SYS_ADMIN (e.g. be root) to use this option.
77
+ # -t, --timeout SEC Timeout (seconds) for the execution. Default: no timeout
78
+ # This option is ignored when --pid is given.
62
79
  # -f, --format FORMAT Output format. FORMAT can only be one of <disasm|raw|inspect>.
63
80
  # Default: disasm
64
- # -l, --limit LIMIT Limit the number of calling "prctl(PR_SET_SECCOMP)".
65
- # The target process will be killed whenever its calling times reaches LIMIT.
66
- # Default: 1
67
- # -o, --output FILE Output result into FILE instead of stdout.
81
+ # -o, --output FILE Write output to FILE instead of stdout.
68
82
  # If multiple seccomp syscalls have been invoked (see --limit),
69
- # results will be written to FILE, FILE_1, FILE_2.. etc.
70
- # For example, "--output out.bpf" and the output files are out.bpf, out_1.bpf, ...
71
- # -p, --pid PID Dump installed seccomp filters of the existing process.
72
- # You must have CAP_SYS_ADMIN (e.g. be root) in order to use this option.
73
-
83
+ # results are written to FILE, FILE_1, FILE_2, etc.
84
+ # For example, with "--output out.bpf" the output files are out.bpf, out_1.bpf, ...
74
85
  ```
75
86
 
76
87
  ### dump
77
88
 
78
- Dumps the seccomp BPF from an execution file.
79
- This work is done by utilizing the `ptrace` syscall.
89
+ Dumps the seccomp BPF from an executable, using the `ptrace` syscall.
80
90
 
81
- NOTICE: beware of the execution file will be executed.
91
+ NOTE: the target executable is actually run, so be careful with untrusted binaries.
82
92
  ```bash
83
93
  $ file spec/binary/twctf-2016-diary
84
94
  # spec/binary/twctf-2016-diary: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=3648e29153ac0259a0b7c3e25537a5334f50107f, not stripped
@@ -123,7 +133,7 @@ $ seccomp-tools dump spec/binary/twctf-2016-diary -f raw | xxd
123
133
 
124
134
  ### disasm
125
135
 
126
- Disassembles the seccomp from raw BPF.
136
+ Disassembles raw seccomp BPF into a readable format.
127
137
  ```bash
128
138
  $ xxd spec/data/twctf-2016-diary.bpf | head -n 3
129
139
  # 00000000: 2000 0000 0000 0000 1500 0001 0200 0000 ...............
@@ -156,21 +166,22 @@ $ seccomp-tools disasm spec/data/twctf-2016-diary.bpf
156
166
 
157
167
  ### asm
158
168
 
159
- Assembles the seccomp rules into raw bytes.
160
- It's very useful when one wants to write custom seccomp rules.
169
+ Assembles seccomp rules into raw bytes.
170
+ Useful when you want to write your own seccomp rules.
161
171
 
162
- Supports labels for jumping and uses syscall names directly. See examples below.
172
+ Supports jump labels and syscall names. See the examples below.
163
173
  ```bash
164
174
  $ seccomp-tools asm
165
175
  # asm - Seccomp bpf assembler.
166
176
  #
167
177
  # Usage: seccomp-tools asm IN_FILE [options]
168
- # -o, --output FILE Output result into FILE instead of stdout.
178
+ # -o, --output FILE Write output to FILE instead of stdout.
169
179
  # -f, --format FORMAT Output format. FORMAT can only be one of <inspect|raw|c_array|c_source|assembly>.
170
180
  # Default: inspect
171
181
  # -a, --arch ARCH Specify architecture.
172
- # Supported architectures are <aarch64|amd64|i386|s390x>.
173
- # Default: amd64
182
+ # Supported architectures are <aarch64|amd64|i386|riscv64|s390x>.
183
+ # Default: auto-detected from the host machine.
184
+ # Set it when the filter targets an architecture other than the host.
174
185
 
175
186
  # Input file for asm
176
187
  $ cat spec/data/libseccomp.asm
@@ -258,7 +269,7 @@ $ seccomp-tools asm spec/data/libseccomp.asm -f raw | seccomp-tools disasm -
258
269
 
259
270
  ```
260
271
 
261
- Since v1.6.0 [not released yet], `asm` has switched to using a yacc-based syntax parser, hence supports more flexible and intuitive syntax!
272
+ Since v1.6.0 [not released yet], `asm` has switched to a yacc-based parser, which allows a more flexible and intuitive syntax!
262
273
 
263
274
  ```bash
264
275
  $ cat spec/data/example.asm
@@ -299,7 +310,7 @@ $ seccomp-tools asm spec/data/example.asm -f raw | seccomp-tools disasm -
299
310
 
300
311
  ```
301
312
 
302
- The output of `seccomp-tools disasm <file> --asm-able` is a valid input of `asm`:
313
+ The output of `seccomp-tools disasm <file> --asm-able` is valid input for `asm`:
303
314
  ```bash
304
315
  $ seccomp-tools disasm spec/data/x32.bpf --asm-able
305
316
  # 0000: A = arch
@@ -344,8 +355,9 @@ $ seccomp-tools emu --help
344
355
  #
345
356
  # Usage: seccomp-tools emu [options] BPF_FILE [sys_nr [arg0 [arg1 ... arg5]]]
346
357
  # -a, --arch ARCH Specify architecture.
347
- # Supported architectures are <aarch64|amd64|i386|s390x>.
348
- # Default: amd64
358
+ # Supported architectures are <aarch64|amd64|i386|riscv64|s390x>.
359
+ # Default: auto-detected from the host machine.
360
+ # Set it when the filter targets an architecture other than the host.
349
361
  # -q, --[no-]quiet Run quietly, only show emulation result.
350
362
  # -i, --ip=VAL Set instruction pointer.
351
363
 
@@ -368,6 +380,214 @@ $ seccomp-tools emu spec/data/libseccomp.bpf write 0x3
368
380
 
369
381
  ```
370
382
 
383
+ ### Explain
384
+
385
+ Summarizes a whole filter as a per-action policy: which syscalls end in `ALLOW`, `KILL`, `ERRNO`, etc.,
386
+ and under what argument constraints. The input can be a dumped BPF file, an executable (its seccomp is
387
+ dumped first, like `dump`), or a running process via `--pid`.
388
+ ```bash
389
+ $ seccomp-tools explain --help
390
+ # explain - Summarize a seccomp filter as a per-action policy.
391
+ #
392
+ # Usage: seccomp-tools explain [options] [BPF_FILE|EXEC]
393
+ # -c, --sh-exec <command> Executes the given command (via sh) and explains its seccomp.
394
+ # Use this to pass arguments or pipe things to the executable.
395
+ # e.g. use `-c "./bin > /dev/null"` to keep the program output out of the result.
396
+ # Takes precedence over the positional argument.
397
+ # -l, --limit LIMIT Explain only the first LIMIT installed filters.
398
+ # Only meaningful when the input is an executable or --pid. Default: 1
399
+ # An executable is killed once it reaches LIMIT.
400
+ # -p, --pid PID Explain the seccomp filters installed on an existing process.
401
+ # You must have CAP_SYS_ADMIN (e.g. be root) to use this option.
402
+ # -t, --timeout SEC Timeout (seconds) for the execution. Default: no timeout
403
+ # This option is ignored when --pid is given.
404
+ # -a, --arch ARCH Specify architecture.
405
+ # Supported architectures are <aarch64|amd64|i386|riscv64|s390x>.
406
+ # Default: auto-detected from the host machine.
407
+ # Set it when the filter targets an architecture other than the host.
408
+ # With an executable or --pid the architecture is auto-detected instead.
409
+
410
+ $ seccomp-tools explain spec/data/libseccomp.bpf -a amd64
411
+ # Seccomp policy for spec/data/libseccomp.bpf
412
+ #
413
+ # Architecture: amd64
414
+ #
415
+ # ALLOW:
416
+ # write, close, dup, exit
417
+ #
418
+ # ERRNO(5):
419
+ # <default> (any other syscall)
420
+ #
421
+ # KILL:
422
+ # sys_number >= 0x40000000 (x32 ABI)
423
+ #
424
+ # Other architectures: KILL
425
+ ```
426
+
427
+ A more involved example - the 0CTF/TCTF 2023 "Nothing is True" filter, which has separate 32/64-bit
428
+ allowlists and argument checks on `open`, `mmap` and `execve`:
429
+ ```bash
430
+ $ seccomp-tools explain spec/data/tctf-2023-nothing-is-true.bpf -a amd64
431
+ # Seccomp policy for spec/data/tctf-2023-nothing-is-true.bpf
432
+ #
433
+ # Architecture: i386
434
+ #
435
+ # ALLOW:
436
+ # exit, read, write, brk, mmap, munmap, exit_group
437
+ #
438
+ # KILL:
439
+ # <default> (any other syscall)
440
+ #
441
+ # Architecture: amd64
442
+ #
443
+ # ALLOW:
444
+ # close, munmap, brk, exit, exit_group
445
+ # open when filename == 0x31337 && flags == 0x0
446
+ # mmap when prot == 0x2
447
+ # execve when filename == 0x7ffea12f7d0e
448
+ #
449
+ # KILL:
450
+ # sys_number >= 0x40000000 (x32 ABI)
451
+ # <default> (any other syscall)
452
+ #
453
+ # Other architectures: KILL
454
+ ```
455
+
456
+ ### Audit
457
+
458
+ Scans a filter for weaknesses and likely escape routes - a missing architecture or x32 guard, a
459
+ permissive (denylist) default, equivalent-syscall gaps (e.g. `execve` blocked but `execveat` not),
460
+ an open/read/write chain, or dangerous syscalls reachable as `ALLOW` - and reports each with a
461
+ severity. It runs on every supported architecture (architecture-specific quirks like amd64's x32 are
462
+ applied only where they exist), and takes the same input as `explain` (a BPF file, an executable, or
463
+ `--pid`).
464
+ ```bash
465
+ $ seccomp-tools audit --help
466
+ # audit - Assess a seccomp filter for weaknesses and escape routes.
467
+ #
468
+ # Usage: seccomp-tools audit [options] [BPF_FILE|EXEC]
469
+ # -c, --sh-exec <command> Executes the given command (via sh) and audits its seccomp.
470
+ # Use this to pass arguments or pipe things to the executable.
471
+ # e.g. use `-c "./bin > /dev/null"` to keep the program output out of the result.
472
+ # Takes precedence over the positional argument.
473
+ # -l, --limit LIMIT Audit only the first LIMIT installed filters.
474
+ # Only meaningful when the input is an executable or --pid. Default: 1
475
+ # An executable is killed once it reaches LIMIT.
476
+ # -p, --pid PID Audit the seccomp filters installed on an existing process.
477
+ # You must have CAP_SYS_ADMIN (e.g. be root) to use this option.
478
+ # -t, --timeout SEC Timeout (seconds) for the execution. Default: no timeout
479
+ # This option is ignored when --pid is given.
480
+ # -a, --arch ARCH Specify architecture.
481
+ # Supported architectures are <aarch64|amd64|i386|riscv64|s390x>.
482
+ # Default: auto-detected from the host machine.
483
+ # Set it when the filter targets an architecture other than the host.
484
+ # With an executable or --pid the architecture is auto-detected instead.
485
+ # -f, --format FORMAT Output format, one of <human|json>.
486
+ # Default: human
487
+ ```
488
+
489
+ Auditing a denylist with several escape routes (the TokyoWesterns CTF 2016 "diary" filter):
490
+ ```bash
491
+ $ seccomp-tools audit spec/data/twctf-2016-diary.bpf -a amd64
492
+ # Seccomp audit of spec/data/twctf-2016-diary.bpf
493
+ # Architectures: amd64
494
+ #
495
+ # [HIGH] Architecture is never validated
496
+ # The filter checks syscall numbers without ever comparing data[4] (arch). Numbers mean different syscalls under
497
+ # another AUDIT_ARCH, so the checks can be dodged by invoking through a different ABI (e.g. i386 numbering on amd64).
498
+ # fix: Compare data[4] against your AUDIT_ARCH_* and KILL every architecture you do not explicitly handle.
499
+ #
500
+ # [HIGH] process_vm_readv is allowed (amd64)
501
+ # process_vm_readv reaches ALLOW - read another process's memory.
502
+ # fix: Block process_vm_readv unless the program genuinely needs it.
503
+ #
504
+ # [HIGH] process_vm_writev is allowed (amd64)
505
+ # process_vm_writev reaches ALLOW - write another process's memory.
506
+ # fix: Block process_vm_writev unless the program genuinely needs it.
507
+ #
508
+ # [HIGH] ptrace is allowed (amd64)
509
+ # ptrace reaches ALLOW - inspect/inject into other processes.
510
+ # fix: Block ptrace unless the program genuinely needs it.
511
+ #
512
+ # [HIGH] Default action is ALLOW (denylist) (amd64)
513
+ # Any syscall the filter does not explicitly block is allowed; a denylist is bypassable by any syscall the author
514
+ # overlooked.
515
+ # fix: Use an allowlist: default to KILL/ERRNO and permit only the needed syscalls.
516
+ #
517
+ # [HIGH] x32 ABI is not guarded (amd64)
518
+ # Syscalls blocked by their native number are reachable via their x32 number (nr | 0x40000000): open, clone, fork,
519
+ # vfork, execve, creat, openat, execveat.
520
+ # fix: After the arch check, KILL when sys_number >= 0x40000000 (or jset 0x40000000).
521
+ #
522
+ # [MEDIUM] connect is allowed (amd64)
523
+ # connect reaches ALLOW - network access (exfiltration).
524
+ # fix: Block connect unless the program genuinely needs it.
525
+ #
526
+ # [MEDIUM] socket is allowed (amd64)
527
+ # socket reaches ALLOW - network access (exfiltration).
528
+ # fix: Block socket unless the program genuinely needs it.
529
+ ```
530
+
531
+ Use `--format json` for CI or tooling:
532
+ ```bash
533
+ $ seccomp-tools audit spec/data/gctf-2019-quals-caas.bpf -a amd64 -f json
534
+ # {
535
+ # "stacked_filters": 1,
536
+ # "reports": [
537
+ # {
538
+ # "source": "spec/data/gctf-2019-quals-caas.bpf",
539
+ # "arches": [
540
+ # "amd64"
541
+ # ],
542
+ # "truncated": false,
543
+ # "findings": [
544
+ # {
545
+ # "id": "dangerous-allow",
546
+ # "severity": "medium",
547
+ # "title": "connect is allowed",
548
+ # "detail": "connect reaches ALLOW - network access (exfiltration).",
549
+ # "arch": "amd64",
550
+ # "syscalls": [
551
+ # "connect"
552
+ # ],
553
+ # "condition": null,
554
+ # "remediation": "Block connect unless the program genuinely needs it."
555
+ # },
556
+ # {
557
+ # "id": "dangerous-allow",
558
+ # "severity": "medium",
559
+ # "title": "socket is allowed",
560
+ # "detail": "socket reaches ALLOW - network access (exfiltration).",
561
+ # "arch": "amd64",
562
+ # "syscalls": [
563
+ # "socket"
564
+ # ],
565
+ # "condition": "family == 0x2 && type == 0x1 && protocol == 0x0",
566
+ # "remediation": "Block socket unless the program genuinely needs it."
567
+ # }
568
+ # ]
569
+ # }
570
+ # ]
571
+ # }
572
+ ```
573
+
574
+ ## Shell Completion
575
+
576
+ `seccomp-tools completion <bash|zsh|fish>` prints a completion script for the given shell. Load it from your shell's startup file:
577
+
578
+ ```bash
579
+ # bash (~/.bashrc)
580
+ eval "$(seccomp-tools completion bash)"
581
+
582
+ # zsh (~/.zshrc, after `compinit`)
583
+ eval "$(seccomp-tools completion zsh)"
584
+
585
+ # fish (~/.config/fish/config.fish)
586
+ seccomp-tools completion fish | source
587
+ ```
588
+
589
+ To avoid the startup cost of evaluating it every time, write the script to the directory your shell loads completions from instead, e.g. `seccomp-tools completion zsh > "${fpath[1]}/_seccomp-tools"`.
590
+
371
591
  ## Screenshots
372
592
 
373
593
  ### Dump
@@ -385,12 +605,13 @@ $ seccomp-tools emu spec/data/libseccomp.bpf write 0x3
385
605
  - [x] x86
386
606
  - [x] arm64 (@saagarjha)
387
607
  - [x] s390x (@iii-i)
608
+ - [x] riscv64
388
609
 
389
- Pull Requests of adding more architectures support are welcome!
610
+ Pull requests adding support for more architectures are welcome!
390
611
 
391
612
  ## Development
392
613
 
393
- I recommend to use [rbenv](https://github.com/rbenv/rbenv) for your Ruby environment.
614
+ I recommend using [rbenv](https://github.com/rbenv/rbenv) to manage your Ruby environment.
394
615
 
395
616
  ### Setup
396
617
 
@@ -409,4 +630,4 @@ I recommend to use [rbenv](https://github.com/rbenv/rbenv) for your Ruby environ
409
630
 
410
631
  Any suggestions or feature requests are welcome!
411
632
  Feel free to file issues or send pull requests.
412
- And, if you like this work, I'll be happy to be [starred](https://github.com/david942j/seccomp-tools/stargazers) :grimacing:
633
+ And if you like this project, consider giving it a [star](https://github.com/david942j/seccomp-tools/stargazers) :grimacing:
@@ -0,0 +1,83 @@
1
+ #compdef seccomp-tools
2
+
3
+ # zsh completion for seccomp-tools
4
+ #
5
+ # Load it with either:
6
+ # eval "$(seccomp-tools completion zsh)" # in ~/.zshrc, after `compinit`
7
+ # or drop this file (named `_seccomp-tools`) into a directory on your $fpath.
8
+
9
+ _seccomp-tools() {
10
+ local -a arches=(aarch64 amd64 i386 riscv64 s390x)
11
+
12
+ # $words is 1-indexed; words[1]=seccomp-tools, words[2]=subcommand.
13
+ if (( CURRENT == 2 )); then
14
+ local -a commands=(
15
+ 'asm:Seccomp bpf assembler'
16
+ 'audit:Assess a filter for weaknesses and escape routes'
17
+ 'completion:Print a shell completion script'
18
+ 'disasm:Disassemble seccomp bpf'
19
+ 'dump:Automatically dump seccomp bpf from executable(s)'
20
+ 'emu:Emulate seccomp rules'
21
+ 'explain:Summarize a filter as a per-action policy'
22
+ )
23
+ _describe 'command' commands
24
+ return
25
+ fi
26
+
27
+ case ${words[2]} in
28
+ asm)
29
+ _arguments \
30
+ '(-o --output)'{-o,--output}'[write output to FILE]:file:_files' \
31
+ '(-f --format)'{-f,--format}'[output format]:format:(inspect raw c_array c_source assembly)' \
32
+ '(-a --arch)'{-a,--arch}"[architecture]:arch:($arches)" \
33
+ '1:input asm file:_files'
34
+ ;;
35
+ disasm)
36
+ _arguments \
37
+ '(-o --output)'{-o,--output}'[write output to FILE]:file:_files' \
38
+ '(-a --arch)'{-a,--arch}"[architecture]:arch:($arches)" \
39
+ '--asm-able[emit output that is valid input for asm]' \
40
+ '(--bpf --no-bpf)--no-bpf[hide the raw BPF bytes]' \
41
+ '(--arg-infer --no-arg-infer)--no-arg-infer[do not infer argument names]' \
42
+ '1:bpf file:_files'
43
+ ;;
44
+ dump)
45
+ _arguments \
46
+ '(-c --sh-exec)'{-c,--sh-exec}'[run command via sh and dump its seccomp]:command:' \
47
+ '(-p --pid)'{-p,--pid}'[dump filters of a running process]:pid:' \
48
+ '(-l --limit)'{-l,--limit}'[dump only the first N filters]:limit:' \
49
+ '(-t --timeout)'{-t,--timeout}'[timeout in seconds]:seconds:' \
50
+ '(-f --format)'{-f,--format}'[output format]:format:(disasm raw inspect)' \
51
+ '(-o --output)'{-o,--output}'[write output to FILE]:file:_files' \
52
+ '1:executable:_files'
53
+ ;;
54
+ audit|explain)
55
+ _arguments \
56
+ '(-c --sh-exec)'{-c,--sh-exec}'[run command via sh]:command:' \
57
+ '(-p --pid)'{-p,--pid}'[analyze a running process]:pid:' \
58
+ '(-l --limit)'{-l,--limit}'[analyze only the first N filters]:limit:' \
59
+ '(-t --timeout)'{-t,--timeout}'[timeout in seconds]:seconds:' \
60
+ '(-a --arch)'{-a,--arch}"[architecture]:arch:($arches)" \
61
+ '(-f --format)'{-f,--format}'[output format]:format:(human json)' \
62
+ '1:bpf file or executable:_files'
63
+ ;;
64
+ emu)
65
+ _arguments \
66
+ '(-a --arch)'{-a,--arch}"[architecture]:arch:($arches)" \
67
+ '(-q --quiet)'{-q,--quiet}'[only show the emulation result]' \
68
+ '(-i --ip)'{-i,--ip}'[set the instruction pointer]:ip:' \
69
+ '1:bpf file:_files'
70
+ ;;
71
+ completion)
72
+ _arguments '1:shell:(bash zsh fish)'
73
+ ;;
74
+ esac
75
+ }
76
+
77
+ # When autoloaded from $fpath the completion system calls this function directly;
78
+ # when eval'd or sourced, register it instead of running it.
79
+ if [ "${funcstack[1]}" = "_seccomp-tools" ]; then
80
+ _seccomp-tools "$@"
81
+ else
82
+ compdef _seccomp-tools seccomp-tools
83
+ fi