Module: Seccomp::Notify
- Defined in:
- lib/seccomp/notify.rb,
lib/seccomp/notify/libc.rb,
lib/seccomp/notify/ioctl.rb,
lib/seccomp/notify/errors.rb,
lib/seccomp/notify/filter.rb,
lib/seccomp/notify/policy.rb,
lib/seccomp/notify/request.rb,
lib/seccomp/notify/structs.rb,
lib/seccomp/notify/version.rb,
lib/seccomp/notify/features.rb,
lib/seccomp/notify/syscalls.rb,
lib/seccomp/notify/constants.rb,
lib/seccomp/notify/fd_passing.rb,
lib/seccomp/notify/supervisor.rb,
lib/seccomp/notify/bpf/builder.rb,
lib/seccomp/notify/bpf/program.rb,
lib/seccomp/notify/target_memory.rb,
lib/seccomp/notify/bpf/instruction.rb
Defined Under Namespace
Modules: BPF, Constants, FdPassing, Features, Filter, Ioctl, Libc, Structs, Syscalls Classes: AlreadyRespondedError, Error, FilterTooLargeError, InvalidPolicyError, MemoryReadError, NotSupportedError, Policy, Request, StaleNotificationError, Supervisor, TargetMemory
Constant Summary collapse
- VERSION =
"0.2.0"
Class Method Summary collapse
-
.features ⇒ Hash<Symbol, Boolean>
Detects optional kernel capabilities with isolated child probes.
-
.notif_sizes ⇒ Hash<Symbol, Integer>
Returns kernel-defined notification structure sizes.
-
.spawn(policy, recv_timeout: 10, **supervisor_options) { ... } ⇒ Supervisor
Starts a filtered child and returns its unfiltered parent supervisor.
-
.supervise_self(policy, supervisor: :spawn, **options, &configure) ⇒ Integer
Installs a filter in the caller and starts a detached supervisor child.
-
.supervisor_alive? ⇒ Boolean?
Returns whether the supervisor-side health pipe is still open.
- .supported? ⇒ Boolean
Class Method Details
.features ⇒ Hash<Symbol, Boolean>
Detects optional kernel capabilities with isolated child probes.
37 38 39 |
# File 'lib/seccomp/notify.rb', line 37 def features @features ||= Features.detect end |
.notif_sizes ⇒ Hash<Symbol, Integer>
Returns kernel-defined notification structure sizes.
43 44 45 |
# File 'lib/seccomp/notify.rb', line 43 def notif_sizes @notif_sizes ||= Libc.notif_sizes end |
.spawn(policy, recv_timeout: 10, **supervisor_options) { ... } ⇒ Supervisor
Starts a filtered child and returns its unfiltered parent supervisor.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/seccomp/notify.rb', line 59 def spawn(policy, recv_timeout: 10, **, &target) raise ArgumentError, "target block is required" unless target unless recv_timeout.is_a?(Numeric) && recv_timeout.real? && recv_timeout.finite? && recv_timeout.positive? raise ArgumentError, "recv_timeout must be positive" end parent_socket, child_socket = UNIXSocket.pair program, install_flags = prepare_supervision(policy, , transfer_fd: child_socket.fileno) health_reader, health_writer = IO.pipe pid = fork do parent_socket.close health_writer.close keep_health_reader(health_reader) listener_fd = Filter.install!(program, flags: install_flags, raw: true) FdPassing.send_fd(child_socket, listener_fd) listener = IO.for_fd(listener_fd, "r") child_socket.close listener.close target.call exit! 0 rescue Exception => error # rubocop:disable Lint/RescueException warn("seccomp-notify target setup failed: #{error.}") exit! 127 end child_socket.close health_reader.close listener = FdPassing.recv_fd(parent_socket, timeout: recv_timeout) parent_socket.close Supervisor.new(listener, target_pid: pid, target_child: true, health_writer:, **) rescue StandardError listener&.close unless listener&.closed? parent_socket&.close unless parent_socket&.closed? child_socket&.close unless child_socket&.closed? health_reader&.close unless health_reader&.closed? health_writer&.close unless health_writer&.closed? terminate_child(pid) raise end |
.supervise_self(policy, supervisor: :spawn, **options, &configure) ⇒ Integer
Installs a filter in the caller and starts a detached supervisor child.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/seccomp/notify.rb', line 102 def supervise_self(policy, supervisor: :spawn, **, &configure) raise ArgumentError, "supervisor must be :spawn or :fork" unless %i[spawn fork].include?(supervisor) raise ArgumentError, "supervisor: :spawn does not support Ruby handler blocks" if supervisor == :spawn && configure selected_features = .fetch(:features, features) raise NotSupportedError, "supervise_self requires CONTINUE when no handler block is given" if !configure && !selected_features[:continue] parent_socket, supervisor_socket = UNIXSocket.pair program, install_flags = prepare_supervision(policy, , transfer_fd: parent_socket.fileno) health_reader, health_writer = IO.pipe target_pid = Process.pid supervisor_pid = case supervisor when :fork fork_supervisor(supervisor_socket, parent_socket, health_reader, health_writer, target_pid, , configure) when :spawn spawn_supervisor(supervisor_socket, parent_socket, health_writer, target_pid, ) end supervisor_socket.close health_writer.close keep_health_reader(health_reader) listener_fd = Filter.install!(program, flags: install_flags, raw: true) FdPassing.send_fd(parent_socket, listener_fd) listener = IO.for_fd(listener_fd, "r") listener.close parent_socket.close Process.detach(supervisor_pid) supervisor_pid rescue StandardError listener&.close unless listener&.closed? parent_socket&.close unless parent_socket&.closed? supervisor_socket&.close unless supervisor_socket&.closed? health_reader&.close unless health_reader&.closed? health_writer&.close unless health_writer&.closed? clear_health_reader(health_reader) terminate_child(supervisor_pid) raise end |
.supervisor_alive? ⇒ Boolean?
Returns whether the supervisor-side health pipe is still open.
50 51 52 53 |
# File 'lib/seccomp/notify.rb', line 50 def supervisor_alive? reader = supervisor_health_reader reader ? IO.select([reader], nil, nil, 0).nil? : nil end |
.supported? ⇒ Boolean
31 32 33 |
# File 'lib/seccomp/notify.rb', line 31 def supported? Features.supported? end |