スクリプト言語でLinuxシステムコールを呼び出す

スクリプト言語でLinuxシステムコールを呼び出す

スクリプト言語から直接Linuxシステムコール(または少なくともlibcラッパー)を呼び出したいと思います。どのスクリプト言語も気にしません。重要なのはコンパイルされないということです。理由は、基本的に依存関係パスにコンパイラを望まないことに関連していますが、ここでもありません。これを可能にするスクリプト言語(シェル、Python、Rubyなど)がありますか?

特に、ランダムシステムコール。

答え1

Perlの機能は以下を可能にしますsyscall

$ perldoc -f syscall
    syscall NUMBER, LIST
            Calls the system call specified as the first element of the list,
            passing the remaining elements as arguments to the system call. If

ドキュメントには write(2) を呼び出す例も示します。

require 'syscall.ph';        # may need to run h2ph
my $s = "hi there\n";
syscall(SYS_write(), fileno(STDOUT), $s, length $s);

持っているとは言えない一度しかし、この機能を試してみてください。さて、この例が実際に動作していることを確認する前に。

これは次のような場合に機能するようですgetrandom

$ perl -E 'require "syscall.ph"; $v = " "x8; syscall(SYS_getrandom(), $v, length $v, 0); print $v' | xxd
00000000: 5790 8a6d 714f 8dbe                      W..mqO..

syscall.phにgetrandomがない場合は、この番号を使用できます。私のDebianテスト(amd64)システムの値は318でした。 Linuxシステムコール番号はアーキテクチャによって異なります。

答え2

Pythonでは、次のものを使用できます。ctypesモジュールは、以下を含む動的ライブラリのすべての機能にアクセスします。syscall()libcから:

import ctypes

SYS_getrandom = 318 # You need to check the syscall number for your target architecture

libc = ctypes.CDLL(None)
_getrandom_syscall = libc.syscall
_getrandom_syscall.restypes = ctypes.c_int
_getrandom_syscall.argtypes = ctypes.c_int, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t, ctypes.c_uint

def getrandom(size, flags=0):
    buf = (ctypes.c_char * size)()
    result = _getrandom_syscall(SYS_getrandom, buf, size, flags)
    if result < 0:
        raise OSError(ctypes.get_errno(), 'getrandom() failed')
    return bytes(buf)

libcにgetrandom()ラッパー関数が含まれている場合は、それを呼び出すこともできます。

import ctypes

libc = ctypes.CDLL(None)
_getrandom = libc.getrandom
_getrandom.restypes = ctypes.c_int
_getrandom.argtypes = ctypes.POINTER(ctypes.c_char), ctypes.c_size_t, ctypes.c_uint

def getrandom(size, flags=0):
    buf = (ctypes.c_char * size)()
    result = _getrandom(buf, size, flags)
    if result < 0:
        raise OSError(ctypes.get_errno(), 'getrandom() failed')
    return bytes(buf)

答え3

Rubyにはsyscall(num [, args...]) → integer機能があります。

たとえば、

irb(main):010:0> syscall 1, 1, "hello\n", 6
hello
=> 6

そしてgetrandom()

irb(main):001:0> a = "aaaaaaaa"
=> "aaaaaaaa"
irb(main):002:0> syscall 318,a,8,0
=> 8
irb(main):003:0> a
=> "\x9Cq\xBE\xD6|\x87\u0016\xC6"
irb(main):004:0> 

関連情報