Module: Seccomp::Notify::Features
- Defined in:
- lib/seccomp/notify/features.rb
Class Method Summary collapse
- .detect ⇒ Object
- .probe ⇒ Object
- .probe_addfd(flags) ⇒ Object
- .probe_install(flags) ⇒ Object
- .probe_response(flags) ⇒ Object
- .supported? ⇒ Boolean
- .terminate_probe(pid) ⇒ Object
- .wait_for_probe(pid) ⇒ Object
Class Method Details
.detect ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/seccomp/notify/features.rb', line 10 def detect disabled = ENV.fetch("SECCOMP_NOTIFY_DISABLE_FEATURES", "").split(",").map(&:strip) result = {user_notif: supported?, continue: false, addfd: false, addfd_send: false, wait_killable_recv: false} return result.freeze unless result[:user_notif] result[:continue] = probe_response(Constants::SECCOMP_USER_NOTIF_FLAG_CONTINUE) result[:addfd] = probe_addfd(0) result[:addfd_send] = probe_addfd(Constants::SECCOMP_ADDFD_FLAG_SEND) result[:wait_killable_recv] = probe_install(Constants::SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV) disabled.each { |name| result[name.to_sym] = false if result.key?(name.to_sym) } result[:addfd_send] = false unless result[:addfd] result.freeze end |
.probe ⇒ Object
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 |
# File 'lib/seccomp/notify/features.rb', line 70 def probe parent, child = UNIXSocket.pair pid = fork do parent.close listener = Filter.install!(BPF::Builder.new(Policy.new { notify :getpid }).build) FdPassing.send_fd(child, listener) Libc::SYSCALL.call(Syscalls.number(:getpid), 0, 0, 0) exit! 0 rescue StandardError exit! 1 end child.close listener = FdPassing.recv_fd(parent, timeout: 2) request = "\0" * Structs::NOTIF_SIZE Ioctl.call(listener, Ioctl::NOTIF_RECV, request) yield listener, request status = wait_for_probe(pid) status.success? rescue SystemCallError, EOFError, Timeout::Error terminate_probe(pid) false ensure listener&.close unless listener&.closed? parent&.close unless parent&.closed? end |
.probe_addfd(flags) ⇒ Object
38 39 40 41 42 43 44 45 46 |
# File 'lib/seccomp/notify/features.rb', line 38 def probe_addfd(flags) File.open("/dev/null") do |source| probe do |listener, request| id = request.unpack1("Q<") injected = Ioctl.call(listener, Ioctl::NOTIF_ADDFD, [id, flags, source.fileno, 0, 0].pack(Structs::ADDFD_FORMAT)) Ioctl.call(listener, Ioctl::NOTIF_SEND, [id, injected, 0, 0].pack(Structs::RESPONSE_FORMAT)) if flags.zero? end end end |
.probe_install(flags) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/seccomp/notify/features.rb', line 48 def probe_install(flags) parent, child = UNIXSocket.pair pid = fork do parent.close listener = Filter.install!(BPF::Builder.new(Policy.new { notify :getpid }).build, flags:) FdPassing.send_fd(child, listener) exit! 0 rescue SystemCallError exit! 1 end child.close listener = FdPassing.recv_fd(parent, timeout: 2) listener.close status = wait_for_probe(pid) status.success? rescue EOFError, Timeout::Error terminate_probe(pid) false ensure parent&.close unless parent&.closed? end |
.probe_response(flags) ⇒ Object
31 32 33 34 35 36 |
# File 'lib/seccomp/notify/features.rb', line 31 def probe_response(flags) probe do |listener, request| response = [request.unpack1("Q<"), 0, 0, flags].pack(Structs::RESPONSE_FORMAT) Ioctl.call(listener, Ioctl::NOTIF_SEND, response) end end |
.supported? ⇒ Boolean
24 25 26 27 28 29 |
# File 'lib/seccomp/notify/features.rb', line 24 def supported? Libc.notif_sizes true rescue SystemCallError, NotSupportedError false end |
.terminate_probe(pid) ⇒ Object
100 101 102 103 |
# File 'lib/seccomp/notify/features.rb', line 100 def terminate_probe(pid) Process.kill("KILL", pid) rescue nil Process.waitpid(pid) rescue nil end |
.wait_for_probe(pid) ⇒ Object
96 97 98 |
# File 'lib/seccomp/notify/features.rb', line 96 def wait_for_probe(pid) Timeout.timeout(2) { Process.waitpid2(pid).last } end |