seccomp-ruby 0.1.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.
- checksums.yaml +7 -0
- data/.rubocop.yml +43 -0
- data/.yardopts +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +132 -0
- data/Rakefile +34 -0
- data/examples/arg_filter.rb +18 -0
- data/examples/basic_allowlist.rb +20 -0
- data/examples/errno_filter.rb +18 -0
- data/examples/notify_supervisor.rb +26 -0
- data/ext/seccomp_ext/const.c +133 -0
- data/ext/seccomp_ext/extconf.rb +45 -0
- data/ext/seccomp_ext/filter.c +685 -0
- data/ext/seccomp_ext/notify.c +184 -0
- data/ext/seccomp_ext/seccomp_ext.c +20 -0
- data/ext/seccomp_ext/seccomp_ext.h +35 -0
- data/ext/seccomp_ext/syscall.c +86 -0
- data/ext/seccomp_ext/util.c +110 -0
- data/lib/libseccomp.rb +77 -0
- data/lib/seccomp/action.rb +154 -0
- data/lib/seccomp/arch.rb +48 -0
- data/lib/seccomp/arg.rb +107 -0
- data/lib/seccomp/attributes.rb +127 -0
- data/lib/seccomp/dsl.rb +33 -0
- data/lib/seccomp/errors.rb +83 -0
- data/lib/seccomp/filter.rb +425 -0
- data/lib/seccomp/low_level.rb +210 -0
- data/lib/seccomp/notification.rb +95 -0
- data/lib/seccomp/notifier.rb +187 -0
- data/lib/seccomp/syscall.rb +44 -0
- data/lib/seccomp/version.rb +6 -0
- data/lib/seccomp.rb +3 -0
- data/sig/seccomp.rbs +300 -0
- metadata +75 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 40f614938f158e9d50bae1663c7a70e706e90e3708c40aad4fe104f51c7e580b
|
|
4
|
+
data.tar.gz: b31a0b00fe82b56887508fdd4d7d87e7fdcb71de4f5751f7d783b1ab5126786d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0a44ae3091f60578544fa965c9ab93f52c29d8e0294fc115cd010028a55d62b4f8e72078413c951ee9116757f3a9720357ba9c6b5b596f4a901044daf888fa46
|
|
7
|
+
data.tar.gz: 0beda9a0f882861e3941cdff169695d951a132a4ad54a360e1f104e4a33b7fc12192888890ca17dc0feebeb83fdf0a16e8fd503233863615d01051ce2f93eb05
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
NewCops: enable
|
|
3
|
+
TargetRubyVersion: 3.1
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
6
|
+
Layout/LineLength:
|
|
7
|
+
Max: 100
|
|
8
|
+
|
|
9
|
+
Metrics/ClassLength:
|
|
10
|
+
Max: 250
|
|
11
|
+
|
|
12
|
+
Metrics/MethodLength:
|
|
13
|
+
Max: 30
|
|
14
|
+
|
|
15
|
+
Style/Documentation:
|
|
16
|
+
Enabled: false
|
|
17
|
+
|
|
18
|
+
Style/StringLiterals:
|
|
19
|
+
EnforcedStyle: double_quotes
|
|
20
|
+
|
|
21
|
+
Gemspec/DevelopmentDependencies:
|
|
22
|
+
Enabled: false
|
|
23
|
+
|
|
24
|
+
Metrics/BlockLength:
|
|
25
|
+
Exclude:
|
|
26
|
+
- "spec/**/*"
|
|
27
|
+
- "*.gemspec"
|
|
28
|
+
|
|
29
|
+
Metrics/AbcSize:
|
|
30
|
+
Exclude:
|
|
31
|
+
- "spec/support/**/*"
|
|
32
|
+
|
|
33
|
+
Naming/MethodParameterName:
|
|
34
|
+
AllowedNames:
|
|
35
|
+
- fd
|
|
36
|
+
- id
|
|
37
|
+
- io
|
|
38
|
+
- op
|
|
39
|
+
- val
|
|
40
|
+
|
|
41
|
+
Security/MarshalLoad:
|
|
42
|
+
Exclude:
|
|
43
|
+
- "spec/live/**/*"
|
data/.yardopts
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yudai Takada
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# seccomp-ruby
|
|
2
|
+
|
|
3
|
+
Native CRuby bindings for [libseccomp](https://github.com/seccomp/libseccomp). The gem exposes
|
|
4
|
+
the C API through `Seccomp::LowLevel` and a Ruby-friendly filter, argument DSL, transaction, and
|
|
5
|
+
user-notification API.
|
|
6
|
+
|
|
7
|
+
> [!WARNING]
|
|
8
|
+
> A loaded seccomp filter cannot be removed or relaxed before the process exits. Ruby itself uses
|
|
9
|
+
> many system calls; an incomplete allowlist can crash the VM immediately. Always validate a filter
|
|
10
|
+
> in a forked child process before using it in production.
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
- Linux and CRuby 3.1 or newer
|
|
15
|
+
- libseccomp 2.5 or newer and its development headers
|
|
16
|
+
- A C compiler
|
|
17
|
+
|
|
18
|
+
On Debian or Ubuntu:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
sudo apt-get install libseccomp-dev build-essential
|
|
22
|
+
bundle install
|
|
23
|
+
bundle exec rake compile
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The gem name is currently `seccomp-ruby`:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
gem "seccomp-ruby"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
Construct and inspect filters in the parent process, but load them only after `fork`:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
require "libseccomp"
|
|
38
|
+
|
|
39
|
+
filter = Seccomp.filter(default: :kill_process) do
|
|
40
|
+
no_new_privs true
|
|
41
|
+
deny :ptrace, errno: Errno::EPERM
|
|
42
|
+
allow :read, :write, :exit, :exit_group, :rt_sigreturn
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
puts filter.to_pfc
|
|
46
|
+
pid = fork do
|
|
47
|
+
filter.load!
|
|
48
|
+
# Run sandboxed work here.
|
|
49
|
+
Process.exit!(0)
|
|
50
|
+
end
|
|
51
|
+
Process.waitpid(pid)
|
|
52
|
+
filter.close
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Argument comparisons use explicit keywords for masked equality:
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
filter.allow(:openat, filter.arg(2).masked_eq(mask: 0o3, value: 0))
|
|
59
|
+
filter.deny(:close, filter.arg(0).eq(2), errno: Errno::EBADF)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Use `Seccomp.supports?` before calling optional APIs. It checks both compile-time availability and
|
|
63
|
+
the runtime API level where applicable:
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
filter.transaction { filter.allow(:read) } if Seccomp.supports?(:transaction)
|
|
67
|
+
filter.precompute if Seccomp.supports?(:precompute)
|
|
68
|
+
notification.add_fd(file) if Seccomp.supports?(:notify_addfd)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## User notifications
|
|
72
|
+
|
|
73
|
+
`Seccomp::Notifier#receive` integrates with Ruby IO waiting and accepts a timeout. Notification
|
|
74
|
+
errors use normal positive errno values at the Ruby boundary:
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
notification.deny(Errno::EPERM) # converted to the kernel's negative errno convention
|
|
78
|
+
notification.respond(error: Errno::EPERM) # direct responses use the same conversion
|
|
79
|
+
notification.continue!
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> [!CAUTION]
|
|
83
|
+
> Notification arguments may contain pointers into another process. If you read through
|
|
84
|
+
> `/proc/<pid>/mem`, call `notification.valid?` again after reading and before responding. This
|
|
85
|
+
> reduces, but cannot eliminate, time-of-check/time-of-use races. `continue!` must only be used when
|
|
86
|
+
> the target syscall is safe to execute with its current arguments.
|
|
87
|
+
|
|
88
|
+
libseccomp keeps one notification listener in process-global state. Closing its `Notifier` or
|
|
89
|
+
owning `Filter` closes and resets that listener. A second notification filter is rejected while
|
|
90
|
+
the listener is active; use one notification supervisor per process.
|
|
91
|
+
|
|
92
|
+
> [!WARNING]
|
|
93
|
+
> A loaded notification filter must allow `close(2)` while its listener is being released. A rule
|
|
94
|
+
> that denies or kills `close(2)` can leave the listener open, and a notification rule for
|
|
95
|
+
> `close(2)` requires a supervisor to answer during cleanup. This cannot be repaired after the
|
|
96
|
+
> irreversible filter is loaded; keep the supervisor running or end the sandbox with
|
|
97
|
+
> `Process.exit!`.
|
|
98
|
+
|
|
99
|
+
If file descriptor 0 is closed when a notification filter is loaded, the gem reserves it with
|
|
100
|
+
`/dev/null` and keeps it open after a successful load; closing it afterward could itself be blocked
|
|
101
|
+
by the irreversible filter. Filters without notification actions leave file descriptor 0 unchanged.
|
|
102
|
+
If a notification load fails after an earlier filter was loaded, the reservation is kept rather than
|
|
103
|
+
risk an internal `close(2)` being intercepted. Rolling back a transaction that added a notification
|
|
104
|
+
rule requires `Filter#reset` or a new notification rule before loading that filter, due to native
|
|
105
|
+
libseccomp state retained by the rejected transaction.
|
|
106
|
+
|
|
107
|
+
## Thread and architecture notes
|
|
108
|
+
|
|
109
|
+
- `tsync` applies a filter to every thread. Ruby VM threads require syscalls such as `futex`,
|
|
110
|
+
`rt_sigprocmask`, and `membarrier`; blocking them may terminate or deadlock the VM.
|
|
111
|
+
- `width: 32` masks comparison values to 32 bits. On 32-bit ABIs, upper halves of 64-bit syscall
|
|
112
|
+
arguments may not be meaningful.
|
|
113
|
+
- x32 and x86_64 are distinct architecture tokens.
|
|
114
|
+
- `Seccomp.api_level=` changes process-global libseccomp state and should be used once at startup.
|
|
115
|
+
|
|
116
|
+
## Development
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
bundle exec rake compile
|
|
120
|
+
bundle exec rake spec:unit
|
|
121
|
+
bundle exec rake spec:live # all load! calls are fork-isolated
|
|
122
|
+
bundle exec rubocop
|
|
123
|
+
bundle exec rbs validate
|
|
124
|
+
bundle exec yard stats --list-undoc
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The live suite must run on Linux. In a container, use `--security-opt seccomp=unconfined`.
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
This project retains its existing MIT license. It dynamically links to libseccomp, which is
|
|
132
|
+
licensed under LGPL-2.1.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "rake/extensiontask"
|
|
5
|
+
require "rspec/core/rake_task"
|
|
6
|
+
|
|
7
|
+
Rake::ExtensionTask.new("seccomp_ext")
|
|
8
|
+
|
|
9
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
|
10
|
+
task.pattern = "spec/{unit,live}/**/*_spec.rb"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
RSpec::Core::RakeTask.new("spec:unit") do |task|
|
|
14
|
+
task.pattern = "spec/unit/**/*_spec.rb"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
RSpec::Core::RakeTask.new("spec:live") do |task|
|
|
18
|
+
task.pattern = "spec/live/**/*_spec.rb"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
require "rubocop/rake_task"
|
|
22
|
+
RuboCop::RakeTask.new
|
|
23
|
+
|
|
24
|
+
desc "Validate RBS signatures"
|
|
25
|
+
task :rbs do
|
|
26
|
+
sh "bundle exec rbs validate"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
desc "Report API documentation coverage"
|
|
30
|
+
task :yard do
|
|
31
|
+
sh "bundle exec yard stats --list-undoc"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
task default: %i[compile spec rubocop]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# WARNING: load! is irreversible. This example loads only in a forked child.
|
|
4
|
+
require "libseccomp"
|
|
5
|
+
|
|
6
|
+
pid = fork do
|
|
7
|
+
filter = Seccomp::Filter.new(:allow)
|
|
8
|
+
filter.deny(:write, filter.arg(0).eq($stdout.fileno), errno: Errno::EPERM)
|
|
9
|
+
filter.load!
|
|
10
|
+
begin
|
|
11
|
+
$stdout.syswrite("blocked\n")
|
|
12
|
+
rescue Errno::EPERM
|
|
13
|
+
$stderr.syswrite("writes to stdout are blocked\n")
|
|
14
|
+
end
|
|
15
|
+
Process.exit!(0)
|
|
16
|
+
end
|
|
17
|
+
_, status = Process.waitpid2(pid)
|
|
18
|
+
abort "sandbox child failed" unless status.success?
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# WARNING: load! is irreversible. This example loads only in a forked child.
|
|
4
|
+
require "libseccomp"
|
|
5
|
+
|
|
6
|
+
required = %i[
|
|
7
|
+
read write close exit exit_group rt_sigreturn rt_sigaction rt_sigprocmask futex mmap munmap
|
|
8
|
+
mprotect madvise brk clock_gettime getpid gettid sigaltstack fstat newfstatat getrandom
|
|
9
|
+
]
|
|
10
|
+
filter = Seccomp::Filter.new(:kill_process)
|
|
11
|
+
required.each { |syscall| filter.allow(syscall) }
|
|
12
|
+
|
|
13
|
+
pid = fork do
|
|
14
|
+
filter.load!
|
|
15
|
+
$stdout.syswrite("sandbox active\n")
|
|
16
|
+
Process.exit!(0)
|
|
17
|
+
end
|
|
18
|
+
_, status = Process.waitpid2(pid)
|
|
19
|
+
filter.close
|
|
20
|
+
abort "sandbox child failed" unless status.success?
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# WARNING: load! is irreversible. This example loads only in a forked child.
|
|
4
|
+
require "libseccomp"
|
|
5
|
+
|
|
6
|
+
pid = fork do
|
|
7
|
+
filter = Seccomp::Filter.new(:allow)
|
|
8
|
+
filter.deny(:openat, errno: Errno::EPERM)
|
|
9
|
+
filter.load!
|
|
10
|
+
begin
|
|
11
|
+
File.read("/etc/hostname")
|
|
12
|
+
rescue Errno::EPERM
|
|
13
|
+
$stdout.syswrite("openat denied with EPERM\n")
|
|
14
|
+
end
|
|
15
|
+
Process.exit!(0)
|
|
16
|
+
end
|
|
17
|
+
_, status = Process.waitpid2(pid)
|
|
18
|
+
abort "sandbox child failed" unless status.success?
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# WARNING: load! is irreversible. This example loads only in a forked child.
|
|
4
|
+
# Pointer arguments must be read before valid? is rechecked to reduce TOCTOU risk.
|
|
5
|
+
require "fiddle"
|
|
6
|
+
require "libseccomp"
|
|
7
|
+
|
|
8
|
+
pid = fork do
|
|
9
|
+
queue = Queue.new
|
|
10
|
+
supervisor = Thread.new do
|
|
11
|
+
notification = queue.pop.receive(timeout: 5)
|
|
12
|
+
notification.valid? ? notification.continue! : nil
|
|
13
|
+
end
|
|
14
|
+
filter = Seccomp::Filter.new(:allow)
|
|
15
|
+
filter.notify(:getppid)
|
|
16
|
+
filter.load!
|
|
17
|
+
queue << filter.notifier
|
|
18
|
+
|
|
19
|
+
syscall = Fiddle::Function.new(Fiddle::Handle::DEFAULT["syscall"],
|
|
20
|
+
[Fiddle::TYPE_LONG], Fiddle::TYPE_LONG)
|
|
21
|
+
syscall.call(Seccomp::Syscall.number(:getppid))
|
|
22
|
+
supervisor.join
|
|
23
|
+
Process.exit!(0)
|
|
24
|
+
end
|
|
25
|
+
_, status = Process.waitpid2(pid)
|
|
26
|
+
abort "sandbox child failed" unless status.success?
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#include "seccomp_ext.h"
|
|
2
|
+
|
|
3
|
+
#define CONST(module, name, value) rb_define_const((module), (name), seccomp_ext_uint32(value))
|
|
4
|
+
|
|
5
|
+
void
|
|
6
|
+
seccomp_ext_init_constants(void)
|
|
7
|
+
{
|
|
8
|
+
VALUE action = rb_define_module_under(mSeccomp, "Action");
|
|
9
|
+
VALUE arch = rb_define_module_under(mSeccomp, "Arch");
|
|
10
|
+
VALUE compare = rb_define_module_under(mSeccomp, "Compare");
|
|
11
|
+
VALUE attribute = rb_define_module_under(mSeccomp, "FilterAttr");
|
|
12
|
+
|
|
13
|
+
CONST(action, "KILL_PROCESS", SCMP_ACT_KILL_PROCESS);
|
|
14
|
+
CONST(action, "KILL_THREAD", SCMP_ACT_KILL_THREAD);
|
|
15
|
+
CONST(action, "KILL", SCMP_ACT_KILL);
|
|
16
|
+
CONST(action, "TRAP", SCMP_ACT_TRAP);
|
|
17
|
+
CONST(action, "NOTIFY", SCMP_ACT_NOTIFY);
|
|
18
|
+
CONST(action, "LOG", SCMP_ACT_LOG);
|
|
19
|
+
CONST(action, "ALLOW", SCMP_ACT_ALLOW);
|
|
20
|
+
#ifdef HAVE_SCMP_ACT_TRAPX
|
|
21
|
+
CONST(action, "TRAPX", SCMP_ACT_TRAPX(0));
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
#ifdef SCMP_ARCH_NATIVE
|
|
25
|
+
CONST(arch, "NATIVE", SCMP_ARCH_NATIVE);
|
|
26
|
+
#endif
|
|
27
|
+
#ifdef SCMP_ARCH_X86
|
|
28
|
+
CONST(arch, "X86", SCMP_ARCH_X86);
|
|
29
|
+
#endif
|
|
30
|
+
#ifdef SCMP_ARCH_X86_64
|
|
31
|
+
CONST(arch, "X86_64", SCMP_ARCH_X86_64);
|
|
32
|
+
#endif
|
|
33
|
+
#ifdef SCMP_ARCH_X32
|
|
34
|
+
CONST(arch, "X32", SCMP_ARCH_X32);
|
|
35
|
+
#endif
|
|
36
|
+
#ifdef SCMP_ARCH_ARM
|
|
37
|
+
CONST(arch, "ARM", SCMP_ARCH_ARM);
|
|
38
|
+
#endif
|
|
39
|
+
#ifdef SCMP_ARCH_AARCH64
|
|
40
|
+
CONST(arch, "AARCH64", SCMP_ARCH_AARCH64);
|
|
41
|
+
#endif
|
|
42
|
+
#ifdef SCMP_ARCH_LOONGARCH64
|
|
43
|
+
CONST(arch, "LOONGARCH64", SCMP_ARCH_LOONGARCH64);
|
|
44
|
+
#endif
|
|
45
|
+
#ifdef SCMP_ARCH_M68K
|
|
46
|
+
CONST(arch, "M68K", SCMP_ARCH_M68K);
|
|
47
|
+
#endif
|
|
48
|
+
#ifdef SCMP_ARCH_MIPS
|
|
49
|
+
CONST(arch, "MIPS", SCMP_ARCH_MIPS);
|
|
50
|
+
#endif
|
|
51
|
+
#ifdef SCMP_ARCH_MIPS64
|
|
52
|
+
CONST(arch, "MIPS64", SCMP_ARCH_MIPS64);
|
|
53
|
+
#endif
|
|
54
|
+
#ifdef SCMP_ARCH_MIPS64N32
|
|
55
|
+
CONST(arch, "MIPS64N32", SCMP_ARCH_MIPS64N32);
|
|
56
|
+
#endif
|
|
57
|
+
#ifdef SCMP_ARCH_MIPSEL
|
|
58
|
+
CONST(arch, "MIPSEL", SCMP_ARCH_MIPSEL);
|
|
59
|
+
#endif
|
|
60
|
+
#ifdef SCMP_ARCH_MIPSEL64
|
|
61
|
+
CONST(arch, "MIPSEL64", SCMP_ARCH_MIPSEL64);
|
|
62
|
+
#endif
|
|
63
|
+
#ifdef SCMP_ARCH_MIPSEL64N32
|
|
64
|
+
CONST(arch, "MIPSEL64N32", SCMP_ARCH_MIPSEL64N32);
|
|
65
|
+
#endif
|
|
66
|
+
#ifdef SCMP_ARCH_PPC
|
|
67
|
+
CONST(arch, "PPC", SCMP_ARCH_PPC);
|
|
68
|
+
#endif
|
|
69
|
+
#ifdef SCMP_ARCH_PPC64
|
|
70
|
+
CONST(arch, "PPC64", SCMP_ARCH_PPC64);
|
|
71
|
+
#endif
|
|
72
|
+
#ifdef SCMP_ARCH_PPC64LE
|
|
73
|
+
CONST(arch, "PPC64LE", SCMP_ARCH_PPC64LE);
|
|
74
|
+
#endif
|
|
75
|
+
#ifdef SCMP_ARCH_S390
|
|
76
|
+
CONST(arch, "S390", SCMP_ARCH_S390);
|
|
77
|
+
#endif
|
|
78
|
+
#ifdef SCMP_ARCH_S390X
|
|
79
|
+
CONST(arch, "S390X", SCMP_ARCH_S390X);
|
|
80
|
+
#endif
|
|
81
|
+
#ifdef SCMP_ARCH_PARISC
|
|
82
|
+
CONST(arch, "PARISC", SCMP_ARCH_PARISC);
|
|
83
|
+
#endif
|
|
84
|
+
#ifdef SCMP_ARCH_PARISC64
|
|
85
|
+
CONST(arch, "PARISC64", SCMP_ARCH_PARISC64);
|
|
86
|
+
#endif
|
|
87
|
+
#ifdef SCMP_ARCH_RISCV64
|
|
88
|
+
CONST(arch, "RISCV64", SCMP_ARCH_RISCV64);
|
|
89
|
+
#endif
|
|
90
|
+
#ifdef SCMP_ARCH_SH
|
|
91
|
+
CONST(arch, "SH", SCMP_ARCH_SH);
|
|
92
|
+
#endif
|
|
93
|
+
#ifdef SCMP_ARCH_SHEB
|
|
94
|
+
CONST(arch, "SHEB", SCMP_ARCH_SHEB);
|
|
95
|
+
#endif
|
|
96
|
+
|
|
97
|
+
CONST(compare, "NE", SCMP_CMP_NE);
|
|
98
|
+
CONST(compare, "LT", SCMP_CMP_LT);
|
|
99
|
+
CONST(compare, "LE", SCMP_CMP_LE);
|
|
100
|
+
CONST(compare, "EQ", SCMP_CMP_EQ);
|
|
101
|
+
CONST(compare, "GE", SCMP_CMP_GE);
|
|
102
|
+
CONST(compare, "GT", SCMP_CMP_GT);
|
|
103
|
+
CONST(compare, "MASKED_EQ", SCMP_CMP_MASKED_EQ);
|
|
104
|
+
|
|
105
|
+
CONST(attribute, "ACT_DEFAULT", SCMP_FLTATR_ACT_DEFAULT);
|
|
106
|
+
CONST(attribute, "ACT_BADARCH", SCMP_FLTATR_ACT_BADARCH);
|
|
107
|
+
CONST(attribute, "CTL_NNP", SCMP_FLTATR_CTL_NNP);
|
|
108
|
+
CONST(attribute, "CTL_TSYNC", SCMP_FLTATR_CTL_TSYNC);
|
|
109
|
+
CONST(attribute, "API_TSKIP", SCMP_FLTATR_API_TSKIP);
|
|
110
|
+
CONST(attribute, "CTL_LOG", SCMP_FLTATR_CTL_LOG);
|
|
111
|
+
CONST(attribute, "CTL_SSB", SCMP_FLTATR_CTL_SSB);
|
|
112
|
+
#ifdef HAVE_CONST_SCMP_FLTATR_CTL_OPTIMIZE
|
|
113
|
+
CONST(attribute, "CTL_OPTIMIZE", SCMP_FLTATR_CTL_OPTIMIZE);
|
|
114
|
+
#endif
|
|
115
|
+
#ifdef HAVE_CONST_SCMP_FLTATR_API_SYSRAWRC
|
|
116
|
+
CONST(attribute, "API_SYSRAWRC", SCMP_FLTATR_API_SYSRAWRC);
|
|
117
|
+
#endif
|
|
118
|
+
#ifdef HAVE_CONST_SCMP_FLTATR_CTL_WAITKILL
|
|
119
|
+
CONST(attribute, "CTL_WAITKILL", SCMP_FLTATR_CTL_WAITKILL);
|
|
120
|
+
#endif
|
|
121
|
+
|
|
122
|
+
rb_define_const(mSeccompLowLevel, "NR_SCMP_ERROR", INT2NUM(__NR_SCMP_ERROR));
|
|
123
|
+
rb_define_const(mSeccompLowLevel, "NR_SCMP_UNDEF", INT2NUM(__NR_SCMP_UNDEF));
|
|
124
|
+
#ifdef SECCOMP_USER_NOTIF_FLAG_CONTINUE
|
|
125
|
+
CONST(mSeccompLowLevel, "USER_NOTIF_FLAG_CONTINUE", SECCOMP_USER_NOTIF_FLAG_CONTINUE);
|
|
126
|
+
#endif
|
|
127
|
+
#ifdef SECCOMP_ADDFD_FLAG_SETFD
|
|
128
|
+
CONST(mSeccompLowLevel, "ADDFD_FLAG_SETFD", SECCOMP_ADDFD_FLAG_SETFD);
|
|
129
|
+
#endif
|
|
130
|
+
#ifdef SECCOMP_ADDFD_FLAG_SEND
|
|
131
|
+
CONST(mSeccompLowLevel, "ADDFD_FLAG_SEND", SECCOMP_ADDFD_FLAG_SEND);
|
|
132
|
+
#endif
|
|
133
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "mkmf"
|
|
4
|
+
|
|
5
|
+
abort "libseccomp is Linux-only" unless RUBY_PLATFORM.include?("linux")
|
|
6
|
+
abort "seccomp.h is required" unless have_header("seccomp.h")
|
|
7
|
+
abort "libseccomp is required" unless have_library("seccomp", "seccomp_init")
|
|
8
|
+
abort "libseccomp >= 2.5 is required" unless have_func("seccomp_notify_alloc", "seccomp.h")
|
|
9
|
+
|
|
10
|
+
%w[
|
|
11
|
+
seccomp_notify_addfd
|
|
12
|
+
seccomp_transaction_start
|
|
13
|
+
seccomp_transaction_commit
|
|
14
|
+
seccomp_transaction_reject
|
|
15
|
+
seccomp_precompute
|
|
16
|
+
seccomp_export_bpf_mem
|
|
17
|
+
].each { |function| have_func(function, "seccomp.h") }
|
|
18
|
+
|
|
19
|
+
if have_macro("SECCOMP_IOCTL_NOTIF_ADDFD", %w[seccomp.h sys/ioctl.h])
|
|
20
|
+
# mkmf exposes extra compiler definitions through this global.
|
|
21
|
+
# rubocop:disable-next Style/GlobalVars
|
|
22
|
+
$defs << "-DHAVE_SECCOMP_IOCTL_NOTIF_ADDFD"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
%w[
|
|
26
|
+
SCMP_ACT_TRAPX
|
|
27
|
+
SCMP_ARCH_LOONGARCH64
|
|
28
|
+
SCMP_ARCH_M68K
|
|
29
|
+
SCMP_ARCH_SH
|
|
30
|
+
SCMP_ARCH_SHEB
|
|
31
|
+
SCMP_ARCH_RISCV64
|
|
32
|
+
].each do |macro|
|
|
33
|
+
# mkmf exposes extra compiler definitions through this global.
|
|
34
|
+
# rubocop:disable-next Style/GlobalVars
|
|
35
|
+
$defs << "-DHAVE_#{macro}" if have_macro(macro, "seccomp.h")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
%w[
|
|
39
|
+
SCMP_FLTATR_CTL_WAITKILL
|
|
40
|
+
SCMP_FLTATR_API_SYSRAWRC
|
|
41
|
+
SCMP_FLTATR_CTL_OPTIMIZE
|
|
42
|
+
].each { |constant| have_const(constant, "seccomp.h") }
|
|
43
|
+
|
|
44
|
+
have_struct_member("struct seccomp_notif_addfd", "newfd_flags", "seccomp.h")
|
|
45
|
+
create_makefile("seccomp_ext")
|