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
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Seccomp
|
|
4
|
+
# One immutable user-notification request.
|
|
5
|
+
class Notification
|
|
6
|
+
# Fields copied from the kernel notification request.
|
|
7
|
+
# @api private
|
|
8
|
+
ATTRIBUTES = %i[id pid flags syscall arch instruction_pointer args].freeze
|
|
9
|
+
attr_reader :id, :pid, :flags, :syscall, :arch, :instruction_pointer, :args
|
|
10
|
+
|
|
11
|
+
# @param notifier [Notifier] response channel
|
|
12
|
+
# @param data [Hash] low-level request fields
|
|
13
|
+
# @return [void]
|
|
14
|
+
# @example `Notification.new(notifier, data)`
|
|
15
|
+
def initialize(notifier, data)
|
|
16
|
+
@notifier = notifier
|
|
17
|
+
ATTRIBUTES.each { |attribute| instance_variable_set("@#{attribute}", data.fetch(attribute)) }
|
|
18
|
+
@args.freeze
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [Boolean] whether the kernel still recognizes the request
|
|
22
|
+
# @raise [Error] if validation fails
|
|
23
|
+
# @example `notification.valid?`
|
|
24
|
+
def valid?
|
|
25
|
+
@notifier.id_valid?(id)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @param val [Integer] syscall return value
|
|
29
|
+
# @param error [Integer, SystemCallError, Class] positive or negative errno
|
|
30
|
+
# @param flags [Integer] response flags
|
|
31
|
+
# @return [nil]
|
|
32
|
+
# @raise [Error] if responding fails
|
|
33
|
+
# @example `notification.respond(val: 3)`
|
|
34
|
+
def respond(val: 0, error: 0, flags: 0)
|
|
35
|
+
error = -errno_number(error).abs unless error.is_a?(Integer) && error.zero?
|
|
36
|
+
@notifier.respond(id: id, val: val, error: error, flags: flags)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @param value [Integer] syscall return value
|
|
40
|
+
# @return [nil]
|
|
41
|
+
# @raise [Error] if responding fails
|
|
42
|
+
# @example `notification.allow(0)`
|
|
43
|
+
def allow(value = 0)
|
|
44
|
+
respond(val: value)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @param errno [Integer, SystemCallError, Class] positive errno
|
|
48
|
+
# @return [nil]
|
|
49
|
+
# @raise [Error] if responding fails
|
|
50
|
+
# @raise [ArgumentError] for an invalid errno
|
|
51
|
+
# @example `notification.deny(Errno::EPERM)`
|
|
52
|
+
def deny(errno)
|
|
53
|
+
number = errno_number(errno)
|
|
54
|
+
raise ArgumentError, "errno must not be zero" if number.zero?
|
|
55
|
+
|
|
56
|
+
respond(error: -number.abs)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @return [nil]
|
|
60
|
+
# @raise [Error] if responding fails
|
|
61
|
+
# @example `notification.continue!`
|
|
62
|
+
def continue!
|
|
63
|
+
respond(flags: LowLevel::USER_NOTIF_FLAG_CONTINUE)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @param io [IO] descriptor to install
|
|
67
|
+
# @param flags [Integer] addfd flags
|
|
68
|
+
# @param newfd [Integer] requested target descriptor
|
|
69
|
+
# @param newfd_flags [Integer] target descriptor flags
|
|
70
|
+
# @return [Integer] installed descriptor
|
|
71
|
+
# @raise [NotSupportedError] when unavailable
|
|
72
|
+
# @example `notification.add_fd(file)`
|
|
73
|
+
def add_fd(io, flags: 0, newfd: 0, newfd_flags: 0)
|
|
74
|
+
@notifier.add_fd(id: id, source_fd: io.fileno, flags: flags,
|
|
75
|
+
newfd: newfd, newfd_flags: newfd_flags)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def errno_number(value)
|
|
81
|
+
number = if value.is_a?(Class) && value < SystemCallError
|
|
82
|
+
value.const_get(:Errno, false) if value.const_defined?(:Errno, false)
|
|
83
|
+
elsif value.is_a?(SystemCallError)
|
|
84
|
+
value.errno
|
|
85
|
+
else
|
|
86
|
+
value
|
|
87
|
+
end
|
|
88
|
+
unless number.is_a?(Integer)
|
|
89
|
+
raise ArgumentError, "errno must be an Integer or system error with an errno"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
number
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "io/wait"
|
|
4
|
+
|
|
5
|
+
module Seccomp
|
|
6
|
+
# Receives and responds to seccomp user notifications.
|
|
7
|
+
class Notifier
|
|
8
|
+
include Enumerable
|
|
9
|
+
|
|
10
|
+
# ponytail: bounded polling avoids a native wakeup channel; replace only if idle cost matters.
|
|
11
|
+
CLOSE_POLL_INTERVAL = 0.1
|
|
12
|
+
private_constant :CLOSE_POLL_INTERVAL
|
|
13
|
+
|
|
14
|
+
# @param filter [Filter] loaded owner filter
|
|
15
|
+
# @param fd [Integer] notification listener descriptor
|
|
16
|
+
# @return [void]
|
|
17
|
+
# @example `Notifier.new(filter, fd)`
|
|
18
|
+
def initialize(filter, fd)
|
|
19
|
+
@filter = filter
|
|
20
|
+
@fd = fd
|
|
21
|
+
@io = IO.for_fd(fd, autoclose: false)
|
|
22
|
+
@receive_lock = filter.__send__(:notification_receive_lock)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @param timeout [Numeric, nil] nonnegative finite real seconds to wait
|
|
26
|
+
# @return [Notification, nil] request or nil on timeout
|
|
27
|
+
# @raise [TypeError, ArgumentError, RangeError] if timeout is invalid
|
|
28
|
+
# @raise [ClosedFilterError] if the owning filter closes
|
|
29
|
+
# @raise [NotificationCanceledError] if the target exits
|
|
30
|
+
# @example `notifier.receive(timeout: 1)`
|
|
31
|
+
def receive(timeout: nil)
|
|
32
|
+
validate_timeout!(timeout)
|
|
33
|
+
deadline = monotonic_time + timeout if timeout
|
|
34
|
+
acquired = acquire_receive_lock(deadline)
|
|
35
|
+
return nil unless acquired
|
|
36
|
+
|
|
37
|
+
receive_locked(remaining_timeout(deadline))
|
|
38
|
+
ensure
|
|
39
|
+
@receive_lock.unlock if acquired
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @yield [Notification] each request
|
|
43
|
+
# @return [Enumerator, Notifier] enumerator or receiver
|
|
44
|
+
# @raise [Error] if receiving fails
|
|
45
|
+
# @example `notifier.each { |notification| notification.continue! }`
|
|
46
|
+
def each
|
|
47
|
+
return enum_for(__method__) unless block_given?
|
|
48
|
+
|
|
49
|
+
loop do
|
|
50
|
+
yield receive
|
|
51
|
+
rescue NotificationCanceledError
|
|
52
|
+
next
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param id [Integer] notification ID
|
|
57
|
+
# @param val [Integer] syscall return value
|
|
58
|
+
# @param error [Integer] kernel-style negative errno
|
|
59
|
+
# @param flags [Integer] response flags
|
|
60
|
+
# @return [nil]
|
|
61
|
+
# @raise [Error] if responding fails
|
|
62
|
+
# @example `notifier.respond(id: id, val: 0)`
|
|
63
|
+
def respond(id:, val: 0, error: 0, flags: 0)
|
|
64
|
+
ensure_open!
|
|
65
|
+
check_notification_result!(LowLevel.notify_respond(@fd, id, val, error, flags),
|
|
66
|
+
call: "seccomp_notify_respond")
|
|
67
|
+
nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @param id [Integer] notification ID
|
|
71
|
+
# @return [Boolean] whether still valid
|
|
72
|
+
# @raise [Error] if validation fails
|
|
73
|
+
# @example `notifier.id_valid?(id)`
|
|
74
|
+
def id_valid?(id)
|
|
75
|
+
ensure_open!
|
|
76
|
+
result = LowLevel.notify_id_valid(@fd, id)
|
|
77
|
+
return true if result.zero?
|
|
78
|
+
|
|
79
|
+
ensure_open!
|
|
80
|
+
return false if [-Errno::ENOENT::Errno, -Errno::EINVAL::Errno].include?(result)
|
|
81
|
+
|
|
82
|
+
check_notification_result!(result, call: "seccomp_notify_id_valid")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @param id [Integer] notification ID
|
|
86
|
+
# @param source_fd [Integer] local descriptor
|
|
87
|
+
# @param flags [Integer] addfd flags
|
|
88
|
+
# @param newfd [Integer] requested target descriptor
|
|
89
|
+
# @param newfd_flags [Integer] target descriptor flags
|
|
90
|
+
# @return [Integer] installed descriptor
|
|
91
|
+
# @raise [NotSupportedError] when unavailable
|
|
92
|
+
# @example `notifier.add_fd(id: id, source_fd: file.fileno)`
|
|
93
|
+
def add_fd(id:, source_fd:, flags: 0, newfd: 0, newfd_flags: 0)
|
|
94
|
+
ensure_open!
|
|
95
|
+
result = LowLevel.notify_addfd(@fd, id, flags, source_fd, newfd, newfd_flags)
|
|
96
|
+
check_notification_result!(result, call: "seccomp_notify_addfd")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# @return [nil]
|
|
100
|
+
# @example `notifier.close`
|
|
101
|
+
def close
|
|
102
|
+
@filter.close
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# @return [Boolean] whether the owner filter is closed
|
|
106
|
+
# @example `notifier.closed?`
|
|
107
|
+
def closed?
|
|
108
|
+
@filter.closed?
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def receive_locked(timeout)
|
|
114
|
+
return nil unless wait_readable(timeout)
|
|
115
|
+
|
|
116
|
+
ensure_open!
|
|
117
|
+
|
|
118
|
+
result, data = LowLevel.notify_receive(@fd)
|
|
119
|
+
if [-Errno::ENOENT::Errno, -Errno::ECANCELED::Errno].include?(result)
|
|
120
|
+
ensure_open!
|
|
121
|
+
raise NotificationCanceledError.new(
|
|
122
|
+
"seccomp_notify_receive failed: notification was canceled",
|
|
123
|
+
errno: -result, call: "seccomp_notify_receive"
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
check_notification_result!(result, call: "seccomp_notify_receive")
|
|
128
|
+
Notification.new(self, data)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def acquire_receive_lock(deadline)
|
|
132
|
+
return @receive_lock.lock unless deadline
|
|
133
|
+
|
|
134
|
+
loop do
|
|
135
|
+
return true if @receive_lock.try_lock
|
|
136
|
+
|
|
137
|
+
remaining = deadline - monotonic_time
|
|
138
|
+
return false if remaining <= 0
|
|
139
|
+
|
|
140
|
+
sleep([remaining, CLOSE_POLL_INTERVAL].min)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def remaining_timeout(deadline)
|
|
145
|
+
deadline && [deadline - monotonic_time, 0].max
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def monotonic_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
149
|
+
|
|
150
|
+
def validate_timeout!(timeout)
|
|
151
|
+
return if timeout.nil?
|
|
152
|
+
unless timeout.is_a?(Numeric) && timeout.real?
|
|
153
|
+
raise TypeError, "timeout must be a real Numeric or nil"
|
|
154
|
+
end
|
|
155
|
+
raise ArgumentError, "time interval must not be negative" if timeout.negative?
|
|
156
|
+
raise RangeError, "time interval must be finite" unless timeout.finite?
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def check_notification_result!(result, call:)
|
|
160
|
+
ensure_open! if result.negative?
|
|
161
|
+
Error.check!(result, call: call)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def wait_readable(timeout)
|
|
165
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout if timeout
|
|
166
|
+
remaining = timeout
|
|
167
|
+
loop do
|
|
168
|
+
ensure_open!
|
|
169
|
+
return true if @io.wait_readable(poll_timeout(remaining))
|
|
170
|
+
|
|
171
|
+
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC) if deadline
|
|
172
|
+
return false if remaining && remaining <= 0
|
|
173
|
+
end
|
|
174
|
+
rescue Errno::EBADF
|
|
175
|
+
ensure_open!
|
|
176
|
+
raise
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def poll_timeout(remaining)
|
|
180
|
+
[remaining || CLOSE_POLL_INTERVAL, CLOSE_POLL_INTERVAL].min
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def ensure_open!
|
|
184
|
+
raise ClosedFilterError, "notification filter is closed" if closed?
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Seccomp
|
|
4
|
+
# Syscall name and number resolution.
|
|
5
|
+
module Syscall
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
# @param value [Symbol, String, Integer] syscall
|
|
9
|
+
# @param arch [Symbol, String, Integer, nil] target architecture
|
|
10
|
+
# @param rewrite [Boolean] rewrite multiplexed syscalls
|
|
11
|
+
# @return [Integer] syscall number
|
|
12
|
+
# @raise [UnknownSyscallError] for an unknown name
|
|
13
|
+
# @example `Syscall.number(:write, arch: :x86_64)`
|
|
14
|
+
def number(value, arch: nil, rewrite: false)
|
|
15
|
+
return value if value.is_a?(Integer)
|
|
16
|
+
|
|
17
|
+
name = value.to_s
|
|
18
|
+
result = if arch
|
|
19
|
+
token = Arch.resolve(arch)
|
|
20
|
+
if rewrite
|
|
21
|
+
LowLevel.syscall_resolve_name_rewrite(token, name)
|
|
22
|
+
else
|
|
23
|
+
LowLevel.syscall_resolve_name_arch(token, name)
|
|
24
|
+
end
|
|
25
|
+
else
|
|
26
|
+
LowLevel.syscall_resolve_name(name)
|
|
27
|
+
end
|
|
28
|
+
return result unless result == LowLevel::NR_SCMP_ERROR
|
|
29
|
+
|
|
30
|
+
raise UnknownSyscallError, "unknown syscall: #{value.inspect}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @param number [Integer] syscall number
|
|
34
|
+
# @param arch [Symbol, String, Integer] target architecture
|
|
35
|
+
# @return [String, nil] syscall name
|
|
36
|
+
# @raise [ArgumentError] unless number is an Integer
|
|
37
|
+
# @example `Syscall.name(1, arch: :x86_64)`
|
|
38
|
+
def name(number, arch: Arch.native)
|
|
39
|
+
raise ArgumentError, "syscall number must be an Integer" unless number.is_a?(Integer)
|
|
40
|
+
|
|
41
|
+
LowLevel.syscall_resolve_num_arch(Arch.resolve(arch), number)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/seccomp.rb
ADDED
data/sig/seccomp.rbs
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
module Seccomp
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
type errno = Integer | SystemCallError | singleton(SystemCallError)
|
|
5
|
+
type action = Integer | Symbol | String | [Symbol, untyped]
|
|
6
|
+
type arch = Integer | Symbol | String
|
|
7
|
+
type syscall = Integer | Symbol | String
|
|
8
|
+
|
|
9
|
+
def self.library_version: () -> LibraryVersion
|
|
10
|
+
def self.api_level: () -> Integer
|
|
11
|
+
def self.api_level=: (Integer) -> Integer
|
|
12
|
+
def self.supports?: (Symbol) -> bool
|
|
13
|
+
def self.filter: (?default: action) { (Filter) -> untyped } -> Filter
|
|
14
|
+
| (?default: action) { () -> untyped } -> Filter
|
|
15
|
+
| (?default: action) -> Filter
|
|
16
|
+
|
|
17
|
+
class LibraryVersion
|
|
18
|
+
attr_accessor major: Integer
|
|
19
|
+
attr_accessor minor: Integer
|
|
20
|
+
attr_accessor micro: Integer
|
|
21
|
+
def to_s: () -> String
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class Error < StandardError
|
|
25
|
+
attr_reader errno: Integer?
|
|
26
|
+
attr_reader call: String?
|
|
27
|
+
def initialize: (?String?, ?errno: Integer?, ?call: String?) -> void
|
|
28
|
+
def self.check!: (Integer, call: String, ?hint: String?) -> Integer
|
|
29
|
+
end
|
|
30
|
+
class PermissionError < Error
|
|
31
|
+
end
|
|
32
|
+
class KernelError < Error
|
|
33
|
+
end
|
|
34
|
+
class ArchError < Error
|
|
35
|
+
end
|
|
36
|
+
class ExistsError < Error
|
|
37
|
+
end
|
|
38
|
+
class InvalidArgumentError < Error
|
|
39
|
+
end
|
|
40
|
+
class NotFoundError < Error
|
|
41
|
+
end
|
|
42
|
+
class OutOfMemoryError < Error
|
|
43
|
+
end
|
|
44
|
+
class NotSupportedError < Error
|
|
45
|
+
end
|
|
46
|
+
class ValueRangeError < Error
|
|
47
|
+
end
|
|
48
|
+
class ThreadSyncError < Error
|
|
49
|
+
end
|
|
50
|
+
class UnknownSyscallError < Error
|
|
51
|
+
end
|
|
52
|
+
class ClosedFilterError < Error
|
|
53
|
+
end
|
|
54
|
+
class NotificationError < Error
|
|
55
|
+
end
|
|
56
|
+
class NotificationCanceledError < NotificationError
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
module LowLevel
|
|
60
|
+
NR_SCMP_ERROR: Integer
|
|
61
|
+
NR_SCMP_UNDEF: Integer
|
|
62
|
+
USER_NOTIF_FLAG_CONTINUE: Integer
|
|
63
|
+
ADDFD_FLAG_SETFD: Integer
|
|
64
|
+
ADDFD_FLAG_SEND: Integer
|
|
65
|
+
|
|
66
|
+
class Context
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.version: () -> [Integer, Integer, Integer]
|
|
70
|
+
def self.api_get: () -> Integer
|
|
71
|
+
def self.api_set: (Integer) -> Integer
|
|
72
|
+
def self.supports?: (Symbol) -> bool
|
|
73
|
+
def self.init: (Integer) -> Context
|
|
74
|
+
def self.release: (Context) -> nil
|
|
75
|
+
def self.closed?: (Context) -> bool
|
|
76
|
+
def self.reset: (Context, Integer) -> Integer
|
|
77
|
+
def self.merge: (Context, Context) -> Integer
|
|
78
|
+
def self.attr_get: (Context, Integer) -> [Integer, Integer]
|
|
79
|
+
def self.attr_set: (Context, Integer, Integer) -> Integer
|
|
80
|
+
def self.arch_add: (Context, Integer) -> Integer
|
|
81
|
+
def self.arch_remove: (Context, Integer) -> Integer
|
|
82
|
+
def self.arch_exist: (Context, Integer) -> Integer
|
|
83
|
+
def self.arch_resolve_name: (String) -> Integer
|
|
84
|
+
def self.arch_native: () -> Integer
|
|
85
|
+
def self.syscall_resolve_name: (String) -> Integer
|
|
86
|
+
def self.syscall_resolve_name_arch: (Integer, String) -> Integer
|
|
87
|
+
def self.syscall_resolve_name_rewrite: (Integer, String) -> Integer
|
|
88
|
+
def self.syscall_resolve_num_arch: (Integer, Integer) -> String?
|
|
89
|
+
def self.rule_add_array: (Context, Integer, Integer, Array[[Integer, Integer, Integer, Integer]]) -> Integer
|
|
90
|
+
def self.rule_add_exact_array: (Context, Integer, Integer, Array[[Integer, Integer, Integer, Integer]]) -> Integer
|
|
91
|
+
def self.syscall_priority: (Context, Integer, Integer) -> Integer
|
|
92
|
+
def self.export_pfc: (Context, Integer) -> Integer
|
|
93
|
+
def self.export_bpf: (Context, Integer) -> Integer
|
|
94
|
+
def self.export_bpf_mem: (Context) -> [Integer, String?]
|
|
95
|
+
def self.precompute: (Context) -> Integer
|
|
96
|
+
def self.load: (Context) -> Integer
|
|
97
|
+
def self.loaded?: (Context) -> bool
|
|
98
|
+
def self.transaction_start: (Context) -> Integer
|
|
99
|
+
def self.transaction_commit: (Context) -> Integer
|
|
100
|
+
def self.transaction_reject: (Context) -> Integer
|
|
101
|
+
def self.notify_fd: (Context) -> Integer
|
|
102
|
+
def self.notify_receive: (Integer) -> [Integer, Hash[Symbol, untyped]?]
|
|
103
|
+
def self.notify_respond: (Integer, Integer, Integer, Integer, Integer) -> Integer
|
|
104
|
+
def self.notify_id_valid: (Integer, Integer) -> Integer
|
|
105
|
+
def self.notify_addfd: (Integer, Integer, Integer, Integer, Integer, Integer) -> Integer
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
module Action
|
|
109
|
+
KILL_PROCESS: Integer
|
|
110
|
+
KILL_THREAD: Integer
|
|
111
|
+
KILL: Integer
|
|
112
|
+
TRAP: Integer
|
|
113
|
+
NOTIFY: Integer
|
|
114
|
+
LOG: Integer
|
|
115
|
+
ALLOW: Integer
|
|
116
|
+
TRAPX: Integer
|
|
117
|
+
|
|
118
|
+
def self.errno: (errno) -> Integer
|
|
119
|
+
def self.trace: (Integer) -> Integer
|
|
120
|
+
def self.trap: (?Integer) -> Integer
|
|
121
|
+
def self.resolve: (action) -> Integer
|
|
122
|
+
def self.describe: (Integer) -> String
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
module Arch
|
|
126
|
+
NATIVE: Integer
|
|
127
|
+
X86: Integer
|
|
128
|
+
X86_64: Integer
|
|
129
|
+
X32: Integer
|
|
130
|
+
ARM: Integer
|
|
131
|
+
AARCH64: Integer
|
|
132
|
+
LOONGARCH64: Integer
|
|
133
|
+
M68K: Integer
|
|
134
|
+
MIPS: Integer
|
|
135
|
+
MIPS64: Integer
|
|
136
|
+
MIPS64N32: Integer
|
|
137
|
+
MIPSEL: Integer
|
|
138
|
+
MIPSEL64: Integer
|
|
139
|
+
MIPSEL64N32: Integer
|
|
140
|
+
PPC: Integer
|
|
141
|
+
PPC64: Integer
|
|
142
|
+
PPC64LE: Integer
|
|
143
|
+
S390: Integer
|
|
144
|
+
S390X: Integer
|
|
145
|
+
PARISC: Integer
|
|
146
|
+
PARISC64: Integer
|
|
147
|
+
RISCV64: Integer
|
|
148
|
+
SH: Integer
|
|
149
|
+
SHEB: Integer
|
|
150
|
+
|
|
151
|
+
def self.all: () -> Hash[Symbol, Integer]
|
|
152
|
+
def self.native: () -> Integer
|
|
153
|
+
def self.resolve: (arch) -> Integer
|
|
154
|
+
def self.name: (Integer) -> Symbol?
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
module Syscall
|
|
158
|
+
def self.number: (syscall, ?arch: arch?, ?rewrite: bool) -> Integer
|
|
159
|
+
def self.name: (Integer, ?arch: arch) -> String?
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
module Compare
|
|
163
|
+
NE: Integer
|
|
164
|
+
LT: Integer
|
|
165
|
+
LE: Integer
|
|
166
|
+
EQ: Integer
|
|
167
|
+
GE: Integer
|
|
168
|
+
GT: Integer
|
|
169
|
+
MASKED_EQ: Integer
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
module FilterAttr
|
|
173
|
+
ACT_DEFAULT: Integer
|
|
174
|
+
ACT_BADARCH: Integer
|
|
175
|
+
CTL_NNP: Integer
|
|
176
|
+
CTL_TSYNC: Integer
|
|
177
|
+
API_TSKIP: Integer
|
|
178
|
+
CTL_LOG: Integer
|
|
179
|
+
CTL_SSB: Integer
|
|
180
|
+
CTL_OPTIMIZE: Integer
|
|
181
|
+
API_SYSRAWRC: Integer
|
|
182
|
+
CTL_WAITKILL: Integer
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
class ArgCmp
|
|
186
|
+
attr_reader arg: Integer
|
|
187
|
+
attr_reader op: Integer
|
|
188
|
+
attr_reader datum_a: Integer
|
|
189
|
+
attr_reader datum_b: Integer
|
|
190
|
+
def initialize: (arg: Integer, op: Symbol, datum_a: Integer, ?datum_b: Integer, ?width: Integer) -> void
|
|
191
|
+
def to_a: () -> [Integer, Integer, Integer, Integer]
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
module Arg
|
|
195
|
+
class Reference
|
|
196
|
+
def initialize: (Integer) -> void
|
|
197
|
+
def ne: (Integer, ?width: Integer) -> ArgCmp
|
|
198
|
+
def lt: (Integer, ?width: Integer) -> ArgCmp
|
|
199
|
+
def le: (Integer, ?width: Integer) -> ArgCmp
|
|
200
|
+
def eq: (Integer, ?width: Integer) -> ArgCmp
|
|
201
|
+
def ge: (Integer, ?width: Integer) -> ArgCmp
|
|
202
|
+
def gt: (Integer, ?width: Integer) -> ArgCmp
|
|
203
|
+
def ==: (Integer, ?width: Integer) -> ArgCmp
|
|
204
|
+
def masked_eq: (mask: Integer, value: Integer, ?width: Integer) -> ArgCmp
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
module DSL
|
|
208
|
+
def arg: (Integer) -> Reference
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
class Filter
|
|
213
|
+
include Arg::DSL
|
|
214
|
+
|
|
215
|
+
def initialize: (?action) -> void
|
|
216
|
+
def self.open: (?action) { (Filter) -> untyped } -> untyped
|
|
217
|
+
| (?action) -> Filter
|
|
218
|
+
def close: () -> nil
|
|
219
|
+
def closed?: () -> bool
|
|
220
|
+
def reset: (?action?) -> self
|
|
221
|
+
def merge!: (Filter) -> self
|
|
222
|
+
def add_arch: (arch) -> self
|
|
223
|
+
def remove_arch: (arch) -> self
|
|
224
|
+
def arch?: (arch) -> bool
|
|
225
|
+
def archs: () -> Array[Symbol]
|
|
226
|
+
def add_rule: (action, syscall, *ArgCmp) -> self
|
|
227
|
+
def add_rule_exact: (action, syscall, *ArgCmp) -> self
|
|
228
|
+
def allow: (syscall, *(syscall | ArgCmp)) -> self
|
|
229
|
+
def deny: (syscall, *ArgCmp, ?errno: errno) -> self
|
|
230
|
+
def kill: (syscall, *ArgCmp) -> self
|
|
231
|
+
def log: (syscall, *ArgCmp) -> self
|
|
232
|
+
def notify: (syscall, *ArgCmp) -> self
|
|
233
|
+
def trap: (syscall, *ArgCmp) -> self
|
|
234
|
+
def trace: (syscall, Integer, *ArgCmp) -> self
|
|
235
|
+
def priority: (syscall, Integer) -> self
|
|
236
|
+
def []: (Symbol | Integer) -> Integer
|
|
237
|
+
def []=: (Symbol | Integer, Integer) -> Integer
|
|
238
|
+
def default_action: () -> Integer
|
|
239
|
+
def bad_arch_action: () -> Integer
|
|
240
|
+
def bad_arch_action=: (action) -> Integer
|
|
241
|
+
def no_new_privs?: () -> bool
|
|
242
|
+
def no_new_privs=: (bool) -> bool
|
|
243
|
+
def tsync?: () -> bool
|
|
244
|
+
def tsync=: (bool) -> bool
|
|
245
|
+
def tskip?: () -> bool
|
|
246
|
+
def tskip=: (bool) -> bool
|
|
247
|
+
def log?: () -> bool
|
|
248
|
+
def log=: (bool) -> bool
|
|
249
|
+
def ssb?: () -> bool
|
|
250
|
+
def ssb=: (bool) -> bool
|
|
251
|
+
def raw_rc?: () -> bool
|
|
252
|
+
def raw_rc=: (bool) -> bool
|
|
253
|
+
def wait_killable?: () -> bool
|
|
254
|
+
def wait_killable=: (bool) -> bool
|
|
255
|
+
def optimize: () -> Integer
|
|
256
|
+
def optimize=: (Integer) -> Integer
|
|
257
|
+
def export_pfc: (IO) -> nil
|
|
258
|
+
def export_bpf: (IO) -> nil
|
|
259
|
+
def to_pfc: () -> String
|
|
260
|
+
def to_bpf: () -> String
|
|
261
|
+
def precompute: () -> self
|
|
262
|
+
def load!: () -> nil
|
|
263
|
+
def loaded?: () -> bool
|
|
264
|
+
def transaction: () { () -> untyped } -> untyped
|
|
265
|
+
def notifier: () -> Notifier
|
|
266
|
+
def arch: (*arch) -> self
|
|
267
|
+
def no_new_privs: (bool) -> self
|
|
268
|
+
def tsync: (bool) -> self
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
class Notifier
|
|
272
|
+
include Enumerable[Notification]
|
|
273
|
+
def initialize: (Filter, Integer) -> void
|
|
274
|
+
def receive: (?timeout: Numeric?) -> Notification?
|
|
275
|
+
def each: () { (Notification) -> untyped } -> self
|
|
276
|
+
| () -> Enumerator[Notification, self]
|
|
277
|
+
def respond: (id: Integer, ?val: Integer, ?error: Integer, ?flags: Integer) -> nil
|
|
278
|
+
def id_valid?: (Integer) -> bool
|
|
279
|
+
def add_fd: (id: Integer, source_fd: Integer, ?flags: Integer, ?newfd: Integer, ?newfd_flags: Integer) -> Integer
|
|
280
|
+
def close: () -> nil
|
|
281
|
+
def closed?: () -> bool
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
class Notification
|
|
285
|
+
attr_reader id: Integer
|
|
286
|
+
attr_reader pid: Integer
|
|
287
|
+
attr_reader flags: Integer
|
|
288
|
+
attr_reader syscall: Integer
|
|
289
|
+
attr_reader arch: Integer
|
|
290
|
+
attr_reader instruction_pointer: Integer
|
|
291
|
+
attr_reader args: Array[Integer]
|
|
292
|
+
def initialize: (Notifier, Hash[Symbol, untyped]) -> void
|
|
293
|
+
def valid?: () -> bool
|
|
294
|
+
def respond: (?val: Integer, ?error: errno, ?flags: Integer) -> nil
|
|
295
|
+
def allow: (?Integer) -> nil
|
|
296
|
+
def deny: (errno) -> nil
|
|
297
|
+
def continue!: () -> nil
|
|
298
|
+
def add_fd: (IO, ?flags: Integer, ?newfd: Integer, ?newfd_flags: Integer) -> Integer
|
|
299
|
+
end
|
|
300
|
+
end
|