パイプでネイティブバイナリを実行する方法はありますか?

パイプでネイティブバイナリを実行する方法はありますか?
echo 'main(){}' | gcc -xc - -o /dev/stdout | ???

UNIXシリーズシステムで出力バイナリを実行する方法はありますか?

編集する:出力を作成できないサンドボックス環境でg ++を実行するには、これが必要です。どのファイル(悪意のある意図がないことを約束します)。

答え1

私はこれが可能だとは思わない。これ実行(2)システムコールには常にファイル名または絶対パスが必要です(ファイル名は常にchar*)。 posix_spawnファイル名にも同様の要件があります。

最も近い方法は、出力を名前付きパイプに接続してパイプで実行しようとすることです。シェルはビットが設定されていないファイルの実行を拒否する可能性がありますが、--x--x--xこれは機能します。パイプラインの作成mkfifo(1)あなたがそれを動作させることができることを確認してください。

別のアプローチは、標準入力を読み込み、ファイルを一時領域に書き込み、そこに--xビットを設定し、分岐して実行し、ファイルを削除することを書くことです。 inodeと内容はプログラムの実行が完了するまで保持されますが、ファイルシステムを介してアクセスすることはできません。プロセスが終了すると、inode が解放され、ストレージ・スペースが使用可能リストに戻されます。

編集する:Matが指摘したように、最初のアプローチはローダーが実行可能ファイルからページを要求しようとするので、うまくいきません。これにより、パイプは不可能なファイルに対するランダム検索トラフィックを生成します。これは2番目の方法のようなものを残します。

答え2

あなたは試すことができますTCC、中間ファイルを作成せずに1ステップでプログラムをコンパイルして実行します。それはあなたにとって問題になる可能性があるgccではありませんが、非常に高速なので、gccよりもあなたの目的に適している可能性があります。

答え3

memfdシステムコールを使用したソリューション:https://github.com/abbat/elfexec

exec.pseudocodeで見つけることができる名前付きファイル記述子をメモリに生成します。

#include <linux/memfd.h>
...
int memfd = syscall(SYS_memfd_create, "someName", 0);
...
write(memfd,... elf-content...);
...
fexecve(memfd, argv, environ);

答え4

それにもかかわらず、gccCファイルを実行可能ファイルにコンパイルすると、多くの一時ファイルが生成されます。

$ echo 'int main(){}' | strace -fe /open -o >(grep CREAT) gcc -xc -
96706 openat(AT_FDCWD, "/tmp/ccxiPEgx.s", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
96707 openat(AT_FDCWD, "/tmp/ccxiPEgx.s", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 0
96706 openat(AT_FDCWD, "/tmp/ccIBSUD4.o", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
96711 openat(AT_FDCWD, "/tmp/ccIBSUD4.o", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
96706 openat(AT_FDCWD, "/tmp/cciAP0FV.res", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
96712 openat(AT_FDCWD, "/tmp/ccfZa2PH.cdtor.c", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
96712 openat(AT_FDCWD, "/tmp/cc4LkCnx.cdtor.o", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
96713 openat(AT_FDCWD, "a.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3

したがって、最終的な実行可能ファイル用に別のものを作成することをお勧めします。

Linuxの場合、事前に削除することができます。たとえば、ここのドキュメントまたはここの文字列を削除された一時ファイル(zshなど)としてまだ実装しているシェルの場合:

$ echo 'int main(){puts("Hello World");}' | { gcc -o /dev/fd/3 -x c  - && /dev/fd/3; } 3<<< ''
<stdin>: In function ‘main’:
<stdin>:1:12: warning: implicit declaration of function ‘puts’ [-Wimplicit-function-declaration]
<stdin>:1:1: note: include ‘<stdio.h>’ or provide a declaration of ‘puts’
Hello World

関連情報