linux上的进程忽略资源限制

linux上的进程忽略资源限制,linux,ipc,Linux,Ipc,不久前,我在stackoverflow上问了一些关于开发在线法官的问题,我发现了很多很好的答案。我已经开始开发一个,我似乎在代码中遇到了一个主要的缺陷 用户提交的源代码将在服务器上编译。这是通过exec()在一个分叉进程中调用gcc来完成的。现在我对CPU时间设置了一个资源限制,一旦超过这个限制,就会向进程发送一个SIGXCPU信号。到目前为止一切都很好。但是,假设有人编写了一个处理SIGXCPU代码本身的恶意代码,那么它将继续在服务器上运行,并可能为有人远程控制服务器开辟一条道路 那么我在这里

不久前,我在stackoverflow上问了一些关于开发在线法官的问题,我发现了很多很好的答案。我已经开始开发一个,我似乎在代码中遇到了一个主要的缺陷

用户提交的源代码将在服务器上编译。这是通过exec()在一个分叉进程中调用gcc来完成的。现在我对CPU时间设置了一个资源限制,一旦超过这个限制,就会向进程发送一个SIGXCPU信号。到目前为止一切都很好。但是,假设有人编写了一个处理SIGXCPU代码本身的恶意代码,那么它将继续在服务器上运行,并可能为有人远程控制服务器开辟一条道路

那么我在这里错过了什么?一定有办法防止这种情况发生

编译模块的基本原型如下所示:

int main() { int pid; int rv; if (!( pid=fork() )) { struct rlimit limit; getrlimit(RLIMIT_CPU, &limit); limit.rlim_cur = 1; setrlimit(RLIMIT_CPU, &limit); //execl() with gcc and source file name } else if(pid) { wait(&rv); } else printf("Error forking\n"); return 0; } int main() { int-pid; int-rv; 如果(!(pid=fork()) { 结构极限; getrlimit(RLIMIT_CPU,&limit); limit.rlim_cur=1; setrlimit(RLIMIT_CPU,&limit); //带有gcc和源文件名的execl() } 否则如果(pid) { 等待(&rv); } 其他的 printf(“错误分叉\n”); 返回0; } 如果源文件包含以下内容

void handler(int signum) { if (signum == SIGXCPU) printf("Caught SIGXCPU signal\n"); } int main() { signal(SIGXCPU, handler); while(1); return 0; } 无效处理程序(int-signum) { if(signum==SIGXCPU) printf(“捕获的SIGXCPU信号\n”); } int main() { 信号(SIGXCPU,处理器); 而(1),; 返回0; }
…这在linux上是个大麻烦,具体来说,用户可以按你说的做。 但是,如果达到硬限制(与您设置的软限制相反),linux将向进程发送sigkill,这将终止进程


(记住,你真的需要在chrooted环境中运行你的东西)

哇。在考虑了这项艰巨的任务大约7分钟后,我为我将要说的任何愚蠢的话提前道歉

这会是什么样子吗

如果目标是允许相对简单的程序运行,而不允许恶意用户破坏您的系统,那么您似乎需要比这更积极主动,否则您将修补漏洞,直到时间结束

至少,我认为您需要去掉用户头文件,并替换您自己的一个包含最低功能的头文件。不允许汇编程序。使用修改后的stdlib和/或内核,在任何尝试的syscall()上都不会操作或终止进程,等等


这里有很多事情要做。

我不想从外部来源验证什么是基本的便携式机器代码……祝你好运有关其他沙箱技巧,请参见:我想我明白了。我将chroot到我的代码目录,然后设置一个硬限制。如果我错了,请纠正我。我认为这会对include路径产生一些影响。你应该复制一个简约的环境,只包含在chrooted环境中编译/运行你想要的东西所需要的东西。(有点像一个只包含编译器/头和它自己目录中的其他小部分的迷你linux安装)是的,非常类似于UVA Judge。谢谢你的建议。我会努力实现它们