0x1eef
630fc0e8a3
The fiddle library is part of Ruby's standard library, and works out of the box for me on HardenedBSD - where as the ffi library raises an error on require
91 lines
2 KiB
Ruby
91 lines
2 KiB
Ruby
require "capsicum/version"
|
|
require "fiddle"
|
|
|
|
module Capsicum
|
|
# @api private
|
|
module LibC
|
|
module_function
|
|
|
|
# Provides a Ruby interface for cap_enter(2)
|
|
# @return [Integer]
|
|
def cap_enter
|
|
Fiddle::Function.new(
|
|
libc["cap_enter"],
|
|
[],
|
|
Fiddle::Types::INT
|
|
).call
|
|
end
|
|
|
|
# Provides a Ruby interface for cap_getmode(2)
|
|
# @param [Fiddle::Pointer] uintp
|
|
# @return [Integer]
|
|
def cap_getmode(uintp)
|
|
Fiddle::Function.new(
|
|
libc["cap_getmode"],
|
|
[Fiddle::Types::INTPTR_T],
|
|
Fiddle::Types::INT
|
|
).call(uintp)
|
|
end
|
|
|
|
def libc
|
|
@libc ||= Fiddle.dlopen Dir["/lib/libc.*"].first
|
|
end
|
|
end
|
|
|
|
# Check if we're in capability mode.
|
|
#
|
|
# @see cap_getmode(2)
|
|
#
|
|
# @return [Boolean] true if we've entered capability mode
|
|
# @raise [Errno::ENOTCAPABLE] - Capsicum not enabled.
|
|
def sandboxed?
|
|
uintp = Fiddle::Pointer.malloc(Fiddle::SIZEOF_UINT)
|
|
ret = LibC.cap_getmode(uintp)
|
|
|
|
if ret == 0
|
|
uintp[0, Fiddle::SIZEOF_UINT].unpack('i') == [1]
|
|
else
|
|
raise SystemCallError.new("cap_getmode", Fiddle.last_error)
|
|
end
|
|
ensure
|
|
uintp.call_free
|
|
end
|
|
|
|
# Enter capability sandbox mode.
|
|
#
|
|
# @see cap_enter(2)
|
|
#
|
|
# @return [Boolean] true if we've entered capability mode.
|
|
# @raise [Errno::ENOTCAPABLE] - Capsicum not enabled.
|
|
def enter!
|
|
ret = LibC.cap_enter
|
|
|
|
if ret == 0
|
|
return true
|
|
else
|
|
raise SystemCallError.new("cap_enter", Fiddle.last_error)
|
|
end
|
|
end
|
|
|
|
# Run the block within a forked process in capability mode and wait for it to
|
|
# complete.
|
|
#
|
|
# @yield block to run within the forked child.
|
|
# @return [Process::Status] exit status of the forked child.
|
|
def within_sandbox
|
|
raise NotImplementedError, "fork() not supported" unless Process.respond_to? :fork
|
|
|
|
return enum_for(:within_sandbox) unless block_given?
|
|
|
|
pid = fork do
|
|
Capsicum.enter!
|
|
yield
|
|
end
|
|
|
|
Process.waitpid2(pid).last
|
|
end
|
|
|
|
module_function :sandboxed?
|
|
module_function :enter!
|
|
module_function :within_sandbox
|
|
end
|