Created
October 23, 2024 12:06
-
-
Save lloeki/27329483d4e83bc5c0c1072c8b9369e5 to your computer and use it in GitHub Desktop.
Ruby and syscalls: `Fiddle` vs `Kernel.syscall`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# docker run --rm -it -v "${PWD}":"${PWD}" -w "${PWD}" ruby:3.3 ruby -w -I. memfd.rb kernel | |
# docker run --rm -it -v "${PWD}":"${PWD}" -w "${PWD}" ruby:3.3 ruby -w -I. memfd.rb fiddle | |
raise unless RUBY_PLATFORM =~ /linux/ | |
SYS_MEMFD_CREATE = case RUBY_PLATFORM | |
when /x86_64/ | |
319 | |
when /i386/ | |
356 | |
when /armv7l/ | |
385 | |
when /(arm|aarch)64/ | |
279 | |
end | |
MFD_CLOEXEC = 0x0001 | |
require 'json' | |
flags = MFD_CLOEXEC | |
filename = 'datadog.tracing_library.json' | |
data = { 'foo' => 'bar' } | |
payload = JSON.dump(data) | |
if ARGV[0] == 'fiddle' | |
# https://www.man7.org/linux/man-pages/man2/syscall.2.html | |
# needs libffi | |
require 'fiddle' | |
# https://docs.ruby-lang.org/en/master/Fiddle.html | |
libc = Fiddle.dlopen(nil) | |
c_syscall = Fiddle::Function.new(libc['syscall'], [Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_UINT], Fiddle::TYPE_LONG) | |
# https://docs.ruby-lang.org/en/master/Fiddle/Pointer.html | |
filename_ptr = Fiddle::Pointer.malloc(filename.bytesize + 1) | |
Fiddle::Pointer.write(filename_ptr, filename) | |
fd = c_syscall.call(SYS_MEMFD_CREATE, filename_ptr, flags) | |
Fiddle.free filename_ptr | |
if fd == -1 | |
raise "error: #{Fiddle.last_error}" | |
end | |
elsif ARGV[0] == 'kernel' | |
# https://docs.ruby-lang.org/en/master/Kernel.html#method-i-syscall | |
# emits warning: deprecated | |
begin | |
fd = Kernel.syscall(SYS_MEMFD_CREATE, filename, flags) | |
rescue SystemCallError => e | |
raise "error: #{e.errno}" | |
end | |
else | |
raise 'error: missing arg' | |
end | |
if fd < 2 | |
raise "unexpected fd value for : #{fd}" | |
else | |
puts "success #{fd}" | |
# https://docs.ruby-lang.org/en/master/IO.html#method-c-new | |
io = IO.new(fd, 'w') | |
# underlying has no encoding, ensure write UTF-8 bytes | |
count = io.write(payload.encode('UTF-8')) | |
p count | |
io.flush | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment