seccomp-notify 0.2.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +5 -3
- data/lib/seccomp/notify/bpf/builder.rb +6 -1
- data/lib/seccomp/notify/constants.rb +2 -0
- data/lib/seccomp/notify/features.rb +50 -36
- data/lib/seccomp/notify/libc.rb +21 -4
- data/lib/seccomp/notify/policy.rb +3 -0
- data/lib/seccomp/notify/request.rb +8 -2
- data/lib/seccomp/notify/supervisor.rb +26 -13
- data/lib/seccomp/notify/target_memory.rb +9 -6
- data/lib/seccomp/notify/version.rb +1 -1
- data/lib/seccomp/notify.rb +7 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1338763ff6ac458c1224576b7763524b57034de1b29423acc2dde48268012dd1
|
|
4
|
+
data.tar.gz: 03dc39b44de12c7bb1401edc303097eb02b389c511e040589c2293cb840d2c41
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9c99782a7d1c9bf43d3069aa1f742f1c3f5e33b40a47014c6e5a3d4803062b8d8239e2df8a915583d056a4441ed438deebde1ad1cc8af9e1a1bdd8b5f95e333f
|
|
7
|
+
data.tar.gz: dd0f9b82f5749bdeb933e6e56c616619f150fadbb9742582f03ef32ff8d8401e7732dff4070b7a0860abcd6bb42ed537047cda119fa314891c99ab51af0bbd4e
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to seccomp-notify are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and versions follow [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## v0.3.0 - 2026-08-24
|
|
9
|
+
|
|
10
|
+
- Kill the issuing thread group without treating a thread ID as a process ID.
|
|
11
|
+
- Keep the listener transfer descriptor reserved so later `sendmsg` calls cannot bypass policy.
|
|
12
|
+
- Reject x32 syscalls, conflicting policy actions, and invalid emulated return values.
|
|
13
|
+
- Preserve the protocol-neutral type of decoded socket addresses.
|
|
14
|
+
- Marshal ioctl and seccomp buffers through native memory for compacting-GC safety.
|
|
15
|
+
- Reduce runtime feature detection from four isolated child probes to two and synchronize supervisor shutdown state.
|
|
16
|
+
|
|
8
17
|
## v0.2.0 - 2026-08-22
|
|
9
18
|
|
|
10
19
|
- Stop supervising a non-child target once it becomes a zombie.
|
data/README.md
CHANGED
|
@@ -102,7 +102,8 @@ syscall, not the process ID.
|
|
|
102
102
|
`supervise_self(policy, supervisor: :fork)` accepts a block that configures the child supervisor.
|
|
103
103
|
The safer `:spawn` form starts a clean Ruby VM and supports the default pass-through handler only.
|
|
104
104
|
Both forms detach the supervisor child, so broad `Process.wait` calls in the target can still
|
|
105
|
-
observe related lifecycle effects.
|
|
105
|
+
observe related lifecycle effects. The default pass-through handler requires `continue!` and Linux
|
|
106
|
+
5.5 or newer; handler-based supervision works on Linux 5.0 or newer.
|
|
106
107
|
|
|
107
108
|
## Responses
|
|
108
109
|
|
|
@@ -137,8 +138,9 @@ If the target calls `exec`, the pipe descriptor is inherited and published as
|
|
|
137
138
|
- I/O submitted through an existing `io_uring` does not pass through the filter;
|
|
138
139
|
`io_uring_setup` is denied by default.
|
|
139
140
|
- If the supervisor dies, blocked notification syscalls return `ENOSYS`.
|
|
140
|
-
- `fcntl`
|
|
141
|
-
|
|
141
|
+
- `fcntl` must remain allowed while Ruby wraps the listener descriptor, so policies that notify or
|
|
142
|
+
deny it are rejected. `sendmsg` may be filtered; only listener transfer on its reserved descriptor
|
|
143
|
+
is allowed, and that descriptor remains open across `exec` to prevent fd-number reuse.
|
|
142
144
|
|
|
143
145
|
## Examples
|
|
144
146
|
|
|
@@ -32,12 +32,17 @@ module Seccomp
|
|
|
32
32
|
private
|
|
33
33
|
|
|
34
34
|
def prologue
|
|
35
|
-
[
|
|
35
|
+
instructions = [
|
|
36
36
|
ins(Constants::BPF_LD_W_ABS, 0, 0, Constants::OFF_ARCH),
|
|
37
37
|
ins(Constants::BPF_JMP_JEQ_K, 1, 0, AUDIT_ARCHES.fetch(@arch)),
|
|
38
38
|
ins(Constants::BPF_RET_K, 0, 0, Constants::SECCOMP_RET_KILL_PROCESS),
|
|
39
39
|
ins(Constants::BPF_LD_W_ABS, 0, 0, Constants::OFF_NR)
|
|
40
40
|
]
|
|
41
|
+
if @arch == :x86_64
|
|
42
|
+
instructions << ins(Constants::BPF_JMP_JGE_K, 0, 1, Constants::X32_SYSCALL_BIT)
|
|
43
|
+
instructions << ins(Constants::BPF_RET_K, 0, 0, Constants::SECCOMP_RET_KILL_PROCESS)
|
|
44
|
+
end
|
|
45
|
+
instructions
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
def linear(decisions)
|
|
@@ -32,7 +32,9 @@ module Seccomp
|
|
|
32
32
|
AUDIT_ARCH_X86_64 = 0xc000_003e
|
|
33
33
|
AUDIT_ARCH_AARCH64 = 0xc000_00b7
|
|
34
34
|
AUDIT_ARCH_I386 = 0x4000_0003
|
|
35
|
+
X32_SYSCALL_BIT = 0x4000_0000
|
|
35
36
|
SYS_SECCOMP = {x86_64: 317, aarch64: 277}.freeze
|
|
37
|
+
SYS_TGKILL = {x86_64: 234, aarch64: 131}.freeze
|
|
36
38
|
|
|
37
39
|
PR_SET_NO_NEW_PRIVS = 38
|
|
38
40
|
PR_SET_PTRACER = 0x5961_6d61
|
|
@@ -12,9 +12,7 @@ module Seccomp
|
|
|
12
12
|
result = {user_notif: supported?, continue: false, addfd: false, addfd_send: false, wait_killable_recv: false}
|
|
13
13
|
return result.freeze unless result[:user_notif]
|
|
14
14
|
|
|
15
|
-
result
|
|
16
|
-
result[:addfd] = probe_addfd(0)
|
|
17
|
-
result[:addfd_send] = probe_addfd(Constants::SECCOMP_ADDFD_FLAG_SEND)
|
|
15
|
+
result.update(probe_responses)
|
|
18
16
|
result[:wait_killable_recv] = probe_install(Constants::SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV)
|
|
19
17
|
disabled.each { |name| result[name.to_sym] = false if result.key?(name.to_sym) }
|
|
20
18
|
result[:addfd_send] = false unless result[:addfd]
|
|
@@ -28,21 +26,36 @@ module Seccomp
|
|
|
28
26
|
false
|
|
29
27
|
end
|
|
30
28
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def probe_addfd(flags)
|
|
29
|
+
def probe_responses
|
|
30
|
+
parent, child = UNIXSocket.pair
|
|
31
|
+
listener = nil
|
|
32
|
+
pid = nil
|
|
39
33
|
File.open("/dev/null") do |source|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
pid = fork do
|
|
35
|
+
parent.close
|
|
36
|
+
listener = Filter.install!(BPF::Builder.new(Policy.new { notify :getpid }).build)
|
|
37
|
+
FdPassing.send_fd(child, listener)
|
|
38
|
+
3.times { Libc::SYSCALL.call(Syscalls.number(:getpid), 0, 0, 0) }
|
|
39
|
+
exit! 0
|
|
40
|
+
rescue StandardError
|
|
41
|
+
exit! 1
|
|
44
42
|
end
|
|
43
|
+
child.close
|
|
44
|
+
listener = FdPassing.recv_fd(parent, timeout: 2)
|
|
45
|
+
result = {
|
|
46
|
+
continue: probe_response(listener, Constants::SECCOMP_USER_NOTIF_FLAG_CONTINUE),
|
|
47
|
+
addfd: probe_addfd(listener, source, 0),
|
|
48
|
+
addfd_send: probe_addfd(listener, source, Constants::SECCOMP_ADDFD_FLAG_SEND)
|
|
49
|
+
}
|
|
50
|
+
return result if wait_for_probe(pid).success?
|
|
45
51
|
end
|
|
52
|
+
{continue: false, addfd: false, addfd_send: false}
|
|
53
|
+
rescue SystemCallError, EOFError, Timeout::Error
|
|
54
|
+
terminate_probe(pid)
|
|
55
|
+
{continue: false, addfd: false, addfd_send: false}
|
|
56
|
+
ensure
|
|
57
|
+
listener&.close unless listener&.closed?
|
|
58
|
+
parent&.close unless parent&.closed?
|
|
46
59
|
end
|
|
47
60
|
|
|
48
61
|
def probe_install(flags)
|
|
@@ -67,30 +80,31 @@ module Seccomp
|
|
|
67
80
|
parent&.close unless parent&.closed?
|
|
68
81
|
end
|
|
69
82
|
|
|
70
|
-
def
|
|
71
|
-
parent, child = UNIXSocket.pair
|
|
72
|
-
pid = fork do
|
|
73
|
-
parent.close
|
|
74
|
-
listener = Filter.install!(BPF::Builder.new(Policy.new { notify :getpid }).build)
|
|
75
|
-
FdPassing.send_fd(child, listener)
|
|
76
|
-
Libc::SYSCALL.call(Syscalls.number(:getpid), 0, 0, 0)
|
|
77
|
-
exit! 0
|
|
78
|
-
rescue StandardError
|
|
79
|
-
exit! 1
|
|
80
|
-
end
|
|
81
|
-
child.close
|
|
82
|
-
listener = FdPassing.recv_fd(parent, timeout: 2)
|
|
83
|
+
def probe_response(listener, flags)
|
|
83
84
|
request = "\0" * Structs::NOTIF_SIZE
|
|
84
85
|
Ioctl.call(listener, Ioctl::NOTIF_RECV, request)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
rescue SystemCallError
|
|
89
|
-
|
|
86
|
+
id = request.unpack1("Q<")
|
|
87
|
+
Ioctl.call(listener, Ioctl::NOTIF_SEND, [id, 0, 0, flags].pack(Structs::RESPONSE_FORMAT))
|
|
88
|
+
true
|
|
89
|
+
rescue SystemCallError
|
|
90
|
+
respond_to_probe(listener, id)
|
|
90
91
|
false
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def probe_addfd(listener, source, flags)
|
|
95
|
+
request = "\0" * Structs::NOTIF_SIZE
|
|
96
|
+
Ioctl.call(listener, Ioctl::NOTIF_RECV, request)
|
|
97
|
+
id = request.unpack1("Q<")
|
|
98
|
+
injected = Ioctl.call(listener, Ioctl::NOTIF_ADDFD, [id, flags, source.fileno, 0, 0].pack(Structs::ADDFD_FORMAT))
|
|
99
|
+
respond_to_probe(listener, id, injected) if flags.zero?
|
|
100
|
+
true
|
|
101
|
+
rescue SystemCallError
|
|
102
|
+
respond_to_probe(listener, id)
|
|
103
|
+
false
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def respond_to_probe(listener, id, value = 0)
|
|
107
|
+
Ioctl.call(listener, Ioctl::NOTIF_SEND, [id, value, 0, 0].pack(Structs::RESPONSE_FORMAT)) if id
|
|
94
108
|
end
|
|
95
109
|
|
|
96
110
|
def wait_for_probe(pid)
|
data/lib/seccomp/notify/libc.rb
CHANGED
|
@@ -46,17 +46,25 @@ module Seccomp
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def seccomp(operation, flags, buffer = 0)
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
with_pointer(buffer) do |pointer|
|
|
50
|
+
SYSCALL.call(Constants::SYS_SECCOMP.fetch(architecture), operation, flags, pointer.to_i)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def tgkill(tgid, tid, signal)
|
|
55
|
+
result = SYSCALL.call(Constants::SYS_TGKILL.fetch(architecture), tgid, tid, signal)
|
|
56
|
+
raise SystemCallError.new("tgkill", Fiddle.last_error) if result.negative?
|
|
57
|
+
|
|
58
|
+
result
|
|
51
59
|
end
|
|
52
60
|
|
|
53
61
|
def ioctl(fd, request, buffer)
|
|
54
|
-
IOCTL.call(fd, request,
|
|
62
|
+
with_pointer(buffer) { |pointer| IOCTL.call(fd, request, pointer) }
|
|
55
63
|
end
|
|
56
64
|
|
|
57
65
|
def poll_hup?(fd)
|
|
58
66
|
buffer = [fd, 1, 0].pack("l<s<s<")
|
|
59
|
-
result = POLL.call(
|
|
67
|
+
result = with_pointer(buffer) { |pointer| POLL.call(pointer, 1, 0) }
|
|
60
68
|
raise SystemCallError.new("poll", Fiddle.last_error) if result.negative?
|
|
61
69
|
|
|
62
70
|
revents = buffer.unpack1("@6S<")
|
|
@@ -71,6 +79,15 @@ module Seccomp
|
|
|
71
79
|
notif, resp, data = buffer.unpack("S<S<S<")
|
|
72
80
|
{notif: notif, resp: resp, data: data}.freeze
|
|
73
81
|
end
|
|
82
|
+
|
|
83
|
+
def with_pointer(buffer)
|
|
84
|
+
return yield buffer unless buffer.is_a?(String)
|
|
85
|
+
|
|
86
|
+
pointer = Fiddle::Pointer.malloc(buffer.bytesize)
|
|
87
|
+
pointer[0, buffer.bytesize] = buffer
|
|
88
|
+
yield(pointer).tap { buffer.replace(pointer[0, buffer.bytesize]) }
|
|
89
|
+
end
|
|
90
|
+
private_class_method :with_pointer
|
|
74
91
|
end
|
|
75
92
|
end
|
|
76
93
|
end
|
|
@@ -87,6 +87,9 @@ module Seccomp
|
|
|
87
87
|
private
|
|
88
88
|
|
|
89
89
|
def validate!
|
|
90
|
+
conflict = (@notifications + @conditional_notifications.map(&:first)).find { |name| @denials.key?(name) }
|
|
91
|
+
raise InvalidPolicyError, "#{conflict} cannot be both notified and denied" if conflict
|
|
92
|
+
|
|
90
93
|
invalid_bootstrap = BOOTSTRAP_SYSCALLS.find { |name| notified?(name) || @denials.key?(name) }
|
|
91
94
|
if invalid_bootstrap
|
|
92
95
|
raise InvalidPolicyError, "#{invalid_bootstrap} must be allowed while transferring the listener fd"
|
|
@@ -79,6 +79,10 @@ module Seccomp
|
|
|
79
79
|
# Emulates a successful syscall return.
|
|
80
80
|
# @return [void]
|
|
81
81
|
def allow!(value = 0)
|
|
82
|
+
unless value.is_a?(Integer) && (-(1 << 63)...(1 << 63)).cover?(value) && !(-Constants::MAX_ERRNO..-1).cover?(value)
|
|
83
|
+
raise ArgumentError, "value must be a signed 64-bit integer outside the errno range"
|
|
84
|
+
end
|
|
85
|
+
|
|
82
86
|
respond!(value:, error: 0, flags: 0)
|
|
83
87
|
end
|
|
84
88
|
|
|
@@ -130,8 +134,10 @@ module Seccomp
|
|
|
130
134
|
|
|
131
135
|
def kill!(signal = "KILL")
|
|
132
136
|
ensure_unresponded!
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
signal = Signal.list.fetch(signal.to_s.delete_prefix("SIG")) { raise ArgumentError, "unknown signal: #{signal.inspect}" } unless signal.is_a?(Integer)
|
|
138
|
+
tgid = Integer(File.read("/proc/#{@tid}/status")[/^Tgid:\s+(\d+)/, 1])
|
|
139
|
+
Libc.tgkill(tgid, @tid, signal)
|
|
140
|
+
error!
|
|
135
141
|
end
|
|
136
142
|
|
|
137
143
|
def mark_pointer_read!
|
|
@@ -54,6 +54,7 @@ module Seccomp
|
|
|
54
54
|
@unknown_handler = ->(request) { request.error!(@default_errno) }
|
|
55
55
|
@error_handler = ->(error, _request) { warn("seccomp-notify supervisor: #{error.full_message(highlight: false, order: :top)}") }
|
|
56
56
|
@receive_mutex = Mutex.new
|
|
57
|
+
@state_mutex = Mutex.new
|
|
57
58
|
@stop = false
|
|
58
59
|
@listener_closed = false
|
|
59
60
|
end
|
|
@@ -95,18 +96,18 @@ module Seccomp
|
|
|
95
96
|
def run
|
|
96
97
|
workers = Array.new(@concurrency) { Thread.new { event_loop } }
|
|
97
98
|
status = wait_for_target
|
|
98
|
-
wait_until_listener_closes if @target_pid &&
|
|
99
|
-
|
|
99
|
+
wait_until_listener_closes if @target_pid && !stopped?
|
|
100
|
+
stop
|
|
100
101
|
workers.each(&:join)
|
|
101
102
|
status
|
|
102
103
|
ensure
|
|
103
|
-
|
|
104
|
+
stop
|
|
104
105
|
@listener.close unless @listener.closed?
|
|
105
106
|
@health_writer&.close unless @health_writer&.closed?
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
def stop
|
|
109
|
-
@stop = true
|
|
110
|
+
@state_mutex.synchronize { @stop = true }
|
|
110
111
|
end
|
|
111
112
|
|
|
112
113
|
private
|
|
@@ -115,7 +116,7 @@ module Seccomp
|
|
|
115
116
|
return wait_until_listener_closes unless @target_pid
|
|
116
117
|
|
|
117
118
|
loop do
|
|
118
|
-
return if
|
|
119
|
+
return if stopped?
|
|
119
120
|
|
|
120
121
|
waited = Process.waitpid2(@target_pid, Process::WNOHANG)
|
|
121
122
|
return waited.last if waited
|
|
@@ -129,7 +130,7 @@ module Seccomp
|
|
|
129
130
|
|
|
130
131
|
def wait_for_non_child
|
|
131
132
|
loop do
|
|
132
|
-
return if
|
|
133
|
+
return if stopped?
|
|
133
134
|
return if target_zombie?
|
|
134
135
|
|
|
135
136
|
Process.kill(0, @target_pid)
|
|
@@ -146,16 +147,16 @@ module Seccomp
|
|
|
146
147
|
end
|
|
147
148
|
|
|
148
149
|
def wait_until_listener_closes
|
|
149
|
-
sleep(@poll_interval) until
|
|
150
|
+
sleep(@poll_interval) until stopped? || listener_closed?
|
|
150
151
|
end
|
|
151
152
|
|
|
152
153
|
def event_loop
|
|
153
|
-
process_one until
|
|
154
|
+
process_one until stopped? || listener_closed?
|
|
154
155
|
rescue IOError, Errno::EBADF, Errno::ENOTCONN
|
|
155
|
-
|
|
156
|
+
stop
|
|
156
157
|
rescue StandardError => error
|
|
157
158
|
warn("seccomp-notify worker failed: #{error.message}")
|
|
158
|
-
|
|
159
|
+
stop
|
|
159
160
|
end
|
|
160
161
|
|
|
161
162
|
def process_one
|
|
@@ -166,17 +167,17 @@ module Seccomp
|
|
|
166
167
|
rescue Errno::EINTR
|
|
167
168
|
retry
|
|
168
169
|
rescue Errno::EAGAIN
|
|
169
|
-
|
|
170
|
+
mark_listener_closed if Libc.poll_hup?(@listener.fileno)
|
|
170
171
|
nil
|
|
171
172
|
rescue Errno::ENOENT
|
|
172
|
-
|
|
173
|
+
mark_listener_closed if Libc.poll_hup?(@listener.fileno)
|
|
173
174
|
nil
|
|
174
175
|
end
|
|
175
176
|
|
|
176
177
|
def receive_request
|
|
177
178
|
return unless IO.select([@listener], nil, nil, @poll_interval)
|
|
178
179
|
if Libc.poll_hup?(@listener.fileno)
|
|
179
|
-
|
|
180
|
+
mark_listener_closed
|
|
180
181
|
return
|
|
181
182
|
end
|
|
182
183
|
|
|
@@ -208,6 +209,18 @@ module Seccomp
|
|
|
208
209
|
request&.close
|
|
209
210
|
end
|
|
210
211
|
end
|
|
212
|
+
|
|
213
|
+
def stopped?
|
|
214
|
+
@state_mutex.synchronize { @stop }
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def listener_closed?
|
|
218
|
+
@state_mutex.synchronize { @listener_closed }
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def mark_listener_closed
|
|
222
|
+
@state_mutex.synchronize { @listener_closed = true }
|
|
223
|
+
end
|
|
211
224
|
end
|
|
212
225
|
end
|
|
213
226
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "ipaddr"
|
|
4
3
|
require "socket"
|
|
4
|
+
require "ipaddr"
|
|
5
5
|
|
|
6
6
|
module Seccomp
|
|
7
7
|
module Notify
|
|
@@ -55,13 +55,16 @@ module Seccomp
|
|
|
55
55
|
case bytes.unpack1("S<")
|
|
56
56
|
when Socket::AF_INET
|
|
57
57
|
raise MemoryReadError, "short AF_INET sockaddr" if length < 16
|
|
58
|
-
|
|
58
|
+
port = bytes.unpack1("@2n")
|
|
59
|
+
host = IPAddr.ntop(bytes.byteslice(4, 4))
|
|
60
|
+
Addrinfo.new(Socket.sockaddr_in(port, host), Socket::AF_INET, 0, 0)
|
|
59
61
|
when Socket::AF_INET6
|
|
60
62
|
raise MemoryReadError, "short AF_INET6 sockaddr" if length < 28
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
port = bytes.unpack1("@2n")
|
|
64
|
+
host = IPAddr.ntop(bytes.byteslice(8, 16))
|
|
65
|
+
scope = bytes.unpack1("@24L<")
|
|
66
|
+
host = "#{host}%#{scope}" unless scope.zero?
|
|
67
|
+
Addrinfo.new(Socket.sockaddr_in(port, host), Socket::AF_INET6, 0, 0)
|
|
65
68
|
when Socket::AF_UNIX
|
|
66
69
|
raw_path = bytes.byteslice(2..).to_s
|
|
67
70
|
path = raw_path.start_with?("\0") ? raw_path : raw_path.split("\0", 2).first
|
data/lib/seccomp/notify.rb
CHANGED
|
@@ -71,8 +71,8 @@ module Seccomp
|
|
|
71
71
|
keep_health_reader(health_reader)
|
|
72
72
|
listener_fd = Filter.install!(program, flags: install_flags, raw: true)
|
|
73
73
|
FdPassing.send_fd(child_socket, listener_fd)
|
|
74
|
+
keep_transfer_socket(child_socket)
|
|
74
75
|
listener = IO.for_fd(listener_fd, "r")
|
|
75
|
-
child_socket.close
|
|
76
76
|
listener.close
|
|
77
77
|
target.call
|
|
78
78
|
exit! 0
|
|
@@ -122,9 +122,9 @@ module Seccomp
|
|
|
122
122
|
keep_health_reader(health_reader)
|
|
123
123
|
listener_fd = Filter.install!(program, flags: install_flags, raw: true)
|
|
124
124
|
FdPassing.send_fd(parent_socket, listener_fd)
|
|
125
|
+
keep_transfer_socket(parent_socket)
|
|
125
126
|
listener = IO.for_fd(listener_fd, "r")
|
|
126
127
|
listener.close
|
|
127
|
-
parent_socket.close
|
|
128
128
|
Process.detach(supervisor_pid)
|
|
129
129
|
supervisor_pid
|
|
130
130
|
rescue StandardError
|
|
@@ -193,6 +193,11 @@ module Seccomp
|
|
|
193
193
|
@supervisor_health_reader = reader
|
|
194
194
|
end
|
|
195
195
|
|
|
196
|
+
def keep_transfer_socket(socket)
|
|
197
|
+
socket.close_on_exec = false
|
|
198
|
+
@listener_transfer_socket = socket
|
|
199
|
+
end
|
|
200
|
+
|
|
196
201
|
def supervisor_health_reader
|
|
197
202
|
return @supervisor_health_reader if defined?(@supervisor_health_reader)
|
|
198
203
|
|