我正在为编程竞赛开发一名评分员。基本上,评分者必须在“孤立”过程中运行解决方案程序。所以,我希望解决方案不要调用任何危害系统调用(例如system(),fork()等)。我可以使用ptrace()来实现吗?
答案 0 :(得分:1)
我认为有两种可能的解决方案:
编辑:我有第一个选项,并在下面包含了必要的代码。使用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)
生成文件:
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;
}
答案 1 :(得分:0)
是的,你可以使用ptrace()来阻止使用PTRACE_SYSCALL选项的某些系统调用。 这是一个使用此功能的项目:
https://github.com/t00sh/p-sandbox/blob/master/p-sandbox.c
如果您只针对Linux,我会建议使用seccomp,这是一种更快的技术,可以将某些系统调用白名单/黑名单或限制其参数。
另一种选择是Google的Native Client。 此项目提供应用程序沙箱的跨平台实现。
您还可以在容器(如docker或LXC)中以非特权用户身份运行应用程序,以限制损坏。
单独使用LD_PRELOAD
是不安全的,因为可执行文件可能带有自己的系统调用实现并绕过底层的libc。