我想知道是否存在在Linux下以沙盒方式运行不受信任的C程序的方法。这样可以防止程序打开文件或网络连接,或进行fork、exec等操作吗?
这将是一个小程序,是一个家庭作业任务,上传到服务器并执行单元测试。因此,程序的生命周期很短。
我想知道是否存在在Linux下以沙盒方式运行不受信任的C程序的方法。这样可以防止程序打开文件或网络连接,或进行fork、exec等操作吗?
这将是一个小程序,是一个家庭作业任务,上传到服务器并执行单元测试。因此,程序的生命周期很短。
我曾使用Systrace在交互和自动模式下对不受信任的程序进行沙箱隔离。它基于ptrace()
的后端,可以在Linux系统上不需要特殊权限进行使用,同时还有一个更快、更强大的后端,需要打补丁修改内核。
在类Unix系统上,也可以使用chroot(1)
创建沙箱,但这并不够简单或安全。Linux Containers和FreeBSD jails是比chroot更好的选择。在Linux上,另一种选择是使用像SELinux或AppArmor这样的安全框架,对于生产系统,我会推荐使用它们。
如果您告诉我们您想做什么,我们就能提供更多帮助。
编辑:
Systrace适用于您的情况,但我认为基于Linux安全模型的东西,如AppArmor或SELinux是更标准、因此更受欢迎的选择,取决于您的发行版。
编辑2:
虽然chroot(1)
在大多数Unix类系统上都可用,但它有很多问题:
可以被打破。如果您要在系统上实际编译或运行不受信任的C程序,您尤其容易受到这个问题的影响。而且,如果你的学生和我的一样,有人肯定会试图打破监狱。
您需要创建一个完整的独立文件系统层次结构,包括执行编译后程序所需的一切。在chroot中不必安装编译器,但应该包含运行编译后程序所需的所有内容。虽然有一些实用工具可以帮助完成这个过程,但仍然不是一件轻松的事情。
您需要维护chroot。由于它是独立的,chroot文件不会随着您的发行版更新而更新。您需要定期重新创建chroot,或者将必要的更新工具包含在其中,这基本上要求它成为一个完整的Linux发行版。您还需要与主机系统同步系统和用户数据(密码、输入文件等)。
chroot()
只能保护文件系统,无法防止恶意程序打开网络套接字或糟糕编写的程序耗尽所有可用资源。
资源使用问题是所有替代方案共同面临的问题。 文件系统配额 可以防止程序填满磁盘。适当的ulimit
(C语言中的setrlimit()
)设置可以防止内存过度使用和任何fork炸弹,以及停止CPU占用。 nice(1)
可以降低这些程序的优先级,使计算机可以用于被认为更重要的任何任务。
我最近写了一篇关于Linux沙盒技术综述的文章。如果你不介意分叉等问题,那么使用Linux容器(lxc)可能是最简单的方法,这在该环境下并不重要。您可以为进程提供只读根文件系统、独立的回环网络连接,而且仍然可以轻松地杀死它并设置内存限制等。
Seccomp会有点困难,因为代码甚至无法分配内存。
Selinux是另一个选择,但我认为它可能比容器更费力。
firejail
会影响程序的 CPU 运行时间吗? - alper您可以使用Qemu快速测试作业。以下步骤在我的五年旧笔记本电脑上只需不到5秒钟。
假设学生需要开发一个程序,该程序接受无符号整数,每个整数占一行,直到出现带有“-1”的行。然后,程序应计算所有整数的平均值并输出“平均值:%f”。以下是如何完全隔离测试程序的方法:
First, get root.bin
from Jslinux, we'll use that as the userland (it has the tcc C-compiler):
wget https://github.com/levskaya/jslinux-deobfuscated/raw/master/root.bin
We want to put the student's submission in root.bin
, so set up the loop device:
sudo losetup /dev/loop0 root.bin
(you could use fuseext2 for this too, but it's not very stable. If it stabilizes, you won't need root for any of this)
Make an empty directory:
mkdir mountpoint
Mount root.bin
:
sudo mount /dev/loop0 mountpoint
Enter the mounted filesystem:
cd mountpoint
.
Fix rights:
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
Copy the submission to the VM:
cp ~/student_assignment.c root/assignment.c
Exit the VM's root FS:
cd ..
sudo umount mountpoint
mkfifo /tmp/guest_output
Open a seperate terminal and start listening for guest output:
dd if=/tmp/guest_output bs=1
In another terminal:
qemu-system-i386 -kernel vmlinuz-3.5.0-27-generic -initrd root.bin -monitor stdio -nographic -serial pipe:/tmp/guestoutput
(I just used the Ubuntu kernel here, but many kernels will work)
When the guest output shows "READY", you can send keys to the VM from the qemu prompt. For example, to test this assignment, you could do
(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
Now Average = 12.000000
should appear on the guest output pipe. If it doesn't, the student failed.
quit
tcclib.h
代替stdio.h
即可。使用seccomp和seccomp-bpf可以用最小的努力实现这一点:https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
好的,感谢所有回答,它们对我帮助很大。但是我建议不要将它们作为原问题提出者的解决方案。所有提到的工具都需要太多的工作来测试学生代码,作为教师、导师或教授。在我看来,在这种情况下最好的方法是使用虚拟机。好吧,它模拟了一个完整的x68系统,与沙盒的意义没有任何关系,但如果我想象一下我的编程老师,这将是最好的选择。因此,在基于Debian的系统上执行“apt-get install virtualbox”,其他系统请访问http://virtualbox.org/,创建虚拟机,添加ISO,点击安装,等待一段时间并且会很幸运。使用起来比设置用户模式Linux或进行一些繁重的strace操作要容易得多...
如果您担心学生会黑客攻击您,我想您可能有权威问题,解决方法是威胁他们,如果您可以证明他们的作品中有恶意软件,您将起诉他们...
如果有一个班级,其中1%的学生能够做出这样的事情,那么不要让他们感到无聊,给他们一些更大的任务,让他们编写更多的代码。综合性学习对每个人都是最好的选择,所以不要依赖旧的僵化结构...
当然,永远不要使用同一台电脑进行重要的事情(比如写证明和考试),而你又用它来浏览网页和测试软件。
对于重要的事情,请使用离线电脑;对于其他所有事情,请使用联网电脑。
然而,对于其他不是偏执的老师(我不想冒犯任何人,我只是认为在成为程序员老师之前,你应该学习有关安全和我们社会的基础知识...)
...我在哪里...对于其他人:
愉快的黑客行动!