私は Systrace を使用して、対話モードと自動モードの両方で、信頼できないプログラムをサンドボックス化しました。 ptrace()
があります
chroot(1)
を使用して、Unix ライクなシステムでサンドボックスを作成することもできます。 、それはそれほど簡単でも安全でもありません。 Linux コンテナーと FreeBSD の監獄は、chroot のより優れた代替手段です。 Linux でのもう 1 つの代替手段は、SELinux や AppArmor などのセキュリティ フレームワークを使用することです。これは、私が実稼働システムに提案するものです。
あなたが何をしたいのかを具体的に教えていただければ、もっとお手伝いできます.
編集:
あなたのケースでは Systrace が有効ですが、ディストリビューションによっては、AppArmor や SELinux などの Linux セキュリティ モデルに基づくものがより標準的であり、したがって推奨される代替手段であると思います。
編集 2:
chroot(1)
の間 ほとんどの (すべて?) Unix ライクなシステムで利用できますが、かなりの問題があります:
-
それは壊れることができます。システムで信頼できない C プログラムを実際にコンパイルまたは実行する場合は、この問題に対して特に脆弱です。そして、あなたの生徒が私のような人なら、誰かが刑務所から脱出しようとするでしょう.
-
タスクに必要なすべてのものを備えた、完全に独立したファイルシステム階層を作成する必要があります。 chroot にコンパイラを含める必要はありませんが、コンパイルされたプログラムを実行するために必要なものはすべて含める必要があります。これを支援するユーティリティはありますが、それでも簡単ではありません。
-
chroot を維持する必要があります。独立しているため、ディストリビューションと共に chroot ファイルが更新されることはありません。 chroot を定期的に再作成するか、chroot に必要な更新ツールを含める必要があります。これには、本格的な Linux ディストリビューションであることが基本的に必要です。また、システムとユーザー データ (パスワード、入力ファイルなど) をホスト システムと同期させる必要があります。
-
chroot()
ファイルシステムのみを保護します。悪意のあるプログラムがネットワーク ソケットを開いたり、不適切なプログラムが利用可能なすべてのリソースを使い果たしたりするのを防ぐことはできません。
リソース使用の問題は、すべての代替案に共通しています。ファイルシステム クォータは、プログラムがディスクをいっぱいにするのを防ぎます。適切な ulimit
(setrlimit()
C) 設定は、メモリの過剰使用やフォーク爆弾から保護し、CPU の浪費を止めることができます。 nice(1)
これらのプログラムの優先度を下げて、より重要と見なされるタスクにコンピュータを問題なく使用できるようにすることができます。
最近、Linux でのサンドボックス化手法の概要を書きました。この環境ではあまり問題にならない fork などを気にしないのであれば、Linux コンテナー (lxc) を使用するのが最も簡単な方法だと思います。プロセスに読み取り専用のルート ファイル システム、分離されたループバック ネットワーク接続を与えることができますが、それでも簡単に強制終了し、メモリ制限などを設定することができます。
コードはメモリを割り当てることさえできないため、seccomp は少し難しくなります。
Selinux はもう 1 つのオプションですが、コンテナよりも手間がかかると思います。
Qemu を使用すると、割り当てをすばやくテストできます。以下の手順は、5 年前のラップトップで 5 秒もかかりません。
学生が、「-1」の行が到着するまで、それぞれの行に unsigned int を取るプログラムを開発しなければならないと仮定しましょう。次に、プログラムはすべての int を平均し、"Average:%f" を出力する必要があります。プログラムを完全に分離してテストする方法は次のとおりです:
<オール>
まず、root.bin
を取得します Jslinux から、それをユーザーランドとして使用します (tcc C コンパイラーがあります):
wget https://github.com/levskaya/jslinux-deobfuscated/raw/master/root.bin
生徒の提出物を root.bin
に入れたい 、ループデバイスをセットアップします:
sudo losetup /dev/loop0 root.bin
(これにも fuseext2 を使用できますが、あまり安定していません。安定すれば、root は必要ありません)
空のディレクトリを作成:
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 カーネルを使用しましたが、多くのカーネルが動作します)
ゲストの出力に「READY」と表示されたら、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/309483. tcclib.h
を使用するだけです stdio.h
の代わりに .