私はプログラミングコンテストの採点者を開発しています。基本的に、採点者は「分離された」プロセスでソリューションプログラムを実行する必要があります。したがって、有害なシステムコール(system()、fork()など)を呼び出さないようにするソリューションが必要です。これを実現するためにptrace()を使用できますか?
2 に答える
私は2つの可能な解決策があると思います:
- LD_PRELOADメカニズムを使用して「shim」を作成し、停止するシステムコールを置き換えます。
setrlimit()を使用して、呼び出しプロセスが実行できることを制限します。残念ながら、これらの制限はプロセスごとではなくユーザーごとの基準であるように思われるため、設定する正しい値を計算することは非常に困難です。
編集:私は最初のオプションが機能していて、以下に必要なコードを含めました。を使用してバイナリをビルドし、次のコマンドmake allでテストしmake runtestsます。
$ make all
gcc -fPIC -shared -Wl,-soname,libmy.so.1 -o libmy.so.1.0 lib.c
ln -sf libmy.so.1.0 libmy.so.1
ln -sf libmy.so.1 libmy.so
gcc -o test test.c
$ make runtests
Without LD_PRELOAD:
./test
in child: retval=9273
in parent: retval=0
With LD_PRELOAD:
LD_PRELOAD=./libmy.so ./test
libmy.so fork!
fork error: error=Operation not permitted (1)
Makefile:
all: libs test
runtests:
@echo Without LD_PRELOAD:
./test
@echo With LD_PRELOAD:
LD_PRELOAD=./libmy.so ./test
libs: lib.c
gcc -fPIC -shared -Wl,-soname,libmy.so.1 -o libmy.so.1.0 lib.c
ln -sf libmy.so.1.0 libmy.so.1
ln -sf libmy.so.1 libmy.so
test: test.c
gcc -o test test.c
clean:
rm -f test libmy.so.1.0 libmy.so.1 libmy.so lib.o
lib.c:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
pid_t fork()
{
printf("libmy.so fork!\n");
errno = EPERM;
return (pid_t)-1;
}
test.c:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(int argc, char **argv)
{
int retval = fork();
if (retval == 0)
printf("in parent: retval=%d\n", retval);
else if (retval > 0)
printf("in child: retval=%d\n", retval);
else
printf("fork error: error=%s (%d)\n", strerror(errno), errno);
return 0;
}
はい、ptrace()を使用して、PTRACE_SYSCALLオプションを使用して特定のシステムコールをブロックできます。この機能を使用したプロジェクトは次のとおりです。
https://github.com/t00sh/p-sandbox/blob/master/p-sandbox.c
Linuxのみを対象とする場合は、代わりにseccompをお勧めします。これは、特定のシステムコールをホワイトリストに登録/ブラックリストに登録するか、引数を制限するためのより高速な手法です。
別の方法は、Googleのネイティブクライアントです。このプロジェクトは、アプリケーションサンドボックスのクロスプラットフォーム実装を提供します。
また、DockerやLXCなどのコンテナー内で非特権ユーザーとしてアプリケーションを実行して、被害を制限することもできます。
LD_PRELOAD実行可能ファイルには独自のsyscall実装が付属しており、基盤となるlibcをバイパスする可能性があるため、単独で使用することは安全ではありません。