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


15

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

特に、getrandom syscallです。


3
getrandomは、単にからランダムなバイトを取り込みます/dev/urandom。あなたは確かにシェルスクリプトからそれを行うことができます。
スティーブ

もちろん、/devまだ利用できない場合を除き、@ steve 。しかし、Perlを想像するのは難しいでしょう!
デロバート

重大なことに、エントロピープールが初期化されるまでこれをブロックする必要があります。これは、ファイルとして/ dev / urandomから読み取るのではありません。
ジョシュルフ

5
/dev/randomブロックが解除されるまで読み取り、それから読み取り/dev/urandomますか?
ビショップ

1
「基本的には、依存関係のパスにコンパイラが必要ないことと関係がありますが、それはここにもそこにもありません」->え?実行時の依存パスを意味する場合、どのような場合でもそうではありません。Cからコンパイルされたバイナリを実行するためにCコンパイラは必要ありません。ターゲットアーキテクチャ向けにコンパイルする能力に依存したくない場合は、その能力がないと思うので、 Python、Bash、または他の実際のスクリプト言語をそのプラットフォームで実行できるようになることはまずありません。
ケビン

回答:


33

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
Perl-プランBハンマー!
トールビョーンラヴンアンデルセン

28

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)

getrandomsyscallではなくlibc 関数を直接呼び出す例を追加できますgetrandomか?それは可能ですか?
ジョシュルフ

@joshlfもちろん可能です。回答を編集しました。
cg909

SYS_getrandom実行時に値の正しい値を動的に検索する方法があるかどうかを知っていますか(現在のプラットフォームに合わせて適切に取得します)。たとえば、/usr/includeヘッダーファイルを解析しますか?
-joshlf

私はそれを試しませんでしたが、あなたはpycparserで運があるかもしれません。
cg909

17

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> 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.