Linuxのサンドボックスで信頼できないCプログラムを実行する方法が存在するかどうか疑問に思っていました。プログラムがファイルを開いたり、ネットワーク接続したり、fork、execしたりするのを妨げる何か。
サーバーにアップロードされ、単体テストが実行される小さなプログラム、宿題です。そのため、プログラムは短命です。
Systrace を使用して、信頼性のないプログラムをインタラクティブモードと自動モードの両方でサンドボックス化しました。 ptrace()
-basedバックエンドがあり、特別な権限なしでLinuxシステムで使用できます。また、カーネルへのパッチ適用が必要な、はるかに高速で強力なバックエンドもあります。
Unixライクなシステムで chroot(1)
を使用してサンドボックスを作成することもできますが、それはそれほど簡単でも安全でもありません。 Linux Containers および FreeBSD jails は、chrootのより良い代替手段です。 Linuxでの別の代替手段は、 SELinux または AppArmor のようなセキュリティフレームワークを使用することです。これは、実稼働システムに提案するものです。
あなたがやりたいことが正確に何であるかを教えていただければ、私たちはあなたをもっと助けることができるでしょう。
編集:
Systraceはあなたの場合には機能しますが、AppArmorやSELinuxのような Linux Security Model に基づいたものが、ディストリビューションに応じて、より標準的な、したがって好ましい代替手段であると思います。
編集2:
chroot(1)
はほとんどの(すべての?)Unixライクなシステムで利用可能ですが、いくつかの問題があります:
破壊することができます。信頼できないCプログラムを実際にシステムでコンパイルまたは実行する場合、この問題に対して特に脆弱です。そして、あなたの生徒が私のようなものである場合、誰かが刑務所から脱出しようとします。
タスクに必要なすべてを備えた完全な独立ファイルシステム階層を作成する必要があります。 chrootにコンパイラーを用意する必要はありませんが、コンパイルされたプログラムを実行するために必要なものはすべて含める必要があります。これを支援するユーティリティはありますが、それはまだ簡単ではありません。
Chrootを維持する必要があります。独立しているため、chrootファイルはディストリビューションとともに更新されません。 chrootを定期的に再作成するか、必要な更新ツールを含める必要があります。これには、本質的に本格的なLinuxディストリビューションが必要です。また、システムおよびユーザーデータ(パスワード、入力ファイルなど)をホストシステムと同期させておく必要があります。
chroot()
はファイルシステムのみを保護します。悪意のあるプログラムがネットワークソケットを開くことや、不適切に作成されたものが利用可能なすべてのリソースを消費することを防ぐことはできません。
リソース使用量の問題は、すべての選択肢に共通しています。 ファイルシステムクォータ は、プログラムがディスクをいっぱいにしないようにします。適切な ulimit
( setrlimit()
in C)設定は、メモリの過剰使用やフォーク爆弾から保護するだけでなく、 CPUが独り占め。 Nice(1)
は、これらのプログラムの優先順位を下げて、問題なくより重要と思われるタスクにコンピューターを使用できるようにします。
Linuxでのサンドボックステクニックの概要 を最近書きました。フォークなどについて気にしないのであれば、この環境ではあまり問題にならないのであれば、最も簡単なアプローチはLinuxコンテナ(lxc)を使用することだと思います。プロセスに読み取り専用のルートファイルシステム、分離されたループバックネットワーク接続を与えることができ、それでも簡単に強制終了してメモリ制限などを設定できます。
コードではメモリを割り当てることさえできないため、Seccompは少し難しくなります。
Selinuxはもう1つのオプションですが、コンテナよりも手間がかかると思います。
Qemuを使用して、割り当てをすばやくテストできます。以下の手順は、私の5歳のラップトップで5秒未満です。
学生が「-1」の行が到着するまで、それぞれ独自の行にある符号なし整数を取るプログラムを開発しなければならないとしましょう。その後、プログラムはすべてのintを平均し、「Average:%f」を出力します。完全に分離されたプログラムをテストする方法は次のとおりです。
まず、Jslinuxからroot.bin
を取得し、それをユーザーランドとして使用します(tcc Cコンパイラーがあります)。
wget https://github.com/levskaya/jslinux-deobfuscated/raw/master/root.bin
生徒の提出物をroot.bin
に入れたいので、ループデバイスをセットアップします。
Sudo losetup /dev/loop0 root.bin
(これにもfuseext2を使用できますが、あまり安定していません。安定すれば、ルートの必要はありません)
空のディレクトリを作成します。
mkdir mountpoint
マウントroot.bin
:
Sudo mount /dev/loop0 mountpoint
マウントされたファイルシステムを入力します。
cd mountpoint
。
修正権:
Sudo chown -R `whoami` .
mkdir -p etc/init.d
vi etc/init.d
:
#!/bin/sh
cd /root
echo READY 2>&1 > /dev/ttyS0
tcc assignment.c 2>&1 > /dev/ttyS0
./a.out 2>&1 > /dev/ttyS0
chmod +x etc/init.d/rcS
サブミッションをVMにコピーします。
cp ~/student_assignment.c root/assignment.c
VMのルートFSを終了します。
cd ..
Sudo umount mountpoint
mkfifo /tmp/guest_output
別のターミナルを開き、ゲスト出力のリッスンを開始します。
dd if=/tmp/guest_output bs=1
別のターミナルで:
qemu-system-i386 -kernel vmlinuz-3.5.0-27-generic -initrd root.bin -monitor stdio -nographic -serial pipe:/tmp/guestoutput
(ここではUbuntuカーネルを使用しましたが、多くのカーネルが動作します)
ゲストの出力に「準備完了」と表示されたら、qemuプロンプトからVMにキーを送信できます。たとえば、この割り当てをテストするには、次のようにします。
(qemu) sendkey 1
(qemu) sendkey 4
(qemu) sendkey ret
(qemu) sendkey 1
(qemu) sendkey 0
(qemu) sendkey ret
(qemu) sendkey minus
(qemu) sendkey 1
(qemu) sendkey ret
これで、Average = 12.000000
がゲスト出力パイプに表示されるはずです。そうでない場合、学生は失敗しました。
quit
テストに合格したプログラムは次のとおりです。 https://stackoverflow.com/a/14424295/30948 。 tcclib.h
の代わりにstdio.h
を使用してください。
ユーザーモードLinux を試してください。 CPUを集中的に使用するジョブのパフォーマンスオーバーヘッドは約1%ですが、I/Oを集中的に使用するジョブでは6倍遅くなる場合があります。
仮想マシン内で実行すると、必要なすべてのセキュリティと制限が提供されます。
[〜#〜] qemu [〜#〜] は、そのすべての作業(アプリケーションのダウンロード、ディスクイメージの更新、QEMUの起動、アプリケーションの実行、保存)に適しています。後で取得するための出力)は、自動化されたテストの実行用にスクリプト化できます。
seccompとseccomp-bpfは、最小限の労力でこれを実現します。 https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
Ptrace(strace)チェックアウトに基づいたサンボックス化の場合:
「sydbox」サンドボックスと「pinktrace」プログラミングライブラリ(C99ですが、 pythonおよびRuby私の知る限り)へのバインディングがあります。
トピックに関連する収集されたリンク:
http://www.diigo.com/user/wierzowiecki/sydbox
(直接リンクではないが、評価ポイントがまだ十分ではないことをごめんなさい)
Firejailは、それを行うための最も包括的なツールの1つです。seccomp、ファイルシステムコンテナー、機能などをサポートします。
これも有望なようです。 syscallインターセプトを使用するLinux用のファイルシステムサンドボックス。