有没有一种编程方式来限制持续时间、内存使用量并以 C/C++ 或 Ruby 中 Linux 程序执行的特权较低的用户身份运行?
由于系统或"无法执行此操作。
sprintf(cmd_str,"/tmp/pro-%d < /tmp/in.txt > /tmp-%d.txt",id,id);
system(cmd_str); // in C
`/tmp/pro-#{id} < /tmp/in.txt > /tmp/out-#{id}.txt` // in Ruby
这两个语句都使该命令以与执行器相同的用户身份运行,根据需要使用整个处理能力和内存。
使用seteuid(2)
系统调用;设置调用进程的有效用户 ID。
以下是 Ruby 示例(见Process::Sys.seteuid
)
Process.uid # => 0
Process.euid # => 0
Process::Sys.seteuid(1000) # Etc::getpwnam('falsetru').uid == 1000
Process.uid # => 0
Process.euid # => 1000
使用 setrlimit
系统调用来限制内存 ( Process::RLIMIT_AS
)。 若要限制程序的运行时间,只能控制进程获取 CPU 时间的总秒数(因此这不考虑休眠或等待 I/O 所花费的时间)。 这是用Process::CPU
完成的.
在设置这些 rlimit 之后,但在使用 Process::exec
调用目标进程之前,先Process::Sys.setgid
后跟 Process::Sys.setuid
删除权限。
目标程序示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ALLOC_SIZE_1 1024
#define ALLOC_SIZE_2 (1024 * 1024 * 5)
int
main(int argc, char *argv[])
{
char *buf;
fprintf(stderr, "[+] uid: %d, gid: %dn", getuid(), getgid());
fprintf(stderr, "[+] trying to allocate %d bytes (should succeed)...n", ALLOC_SIZE_1);
if (NULL == (buf = malloc(ALLOC_SIZE_1))) {
fprintf(stderr, "[!] failed!n");
return -1;
}
fprintf(stderr, "[+] success.n");
free(buf);
fprintf(stderr, "[+] trying to allocate %d bytes (should fail)...n", ALLOC_SIZE_2);
if (NULL != (buf = malloc(ALLOC_SIZE_2))) {
fprintf(stderr, "[!] succeeded! (should have failed.)n");
return -1;
}
fprintf(stderr, "[+] ok. now doing infinite loop (should get killed pretty soon)...n");
for (;;);
return 0;
}
并附带 Ruby 脚本来调用它(以 root 身份运行此脚本,例如 sudo /tmp/foo.rb
):
#!/usr/bin/env ruby
TARGET_GID = 99
TARGET_UID = 99
Process::setrlimit(Process::RLIMIT_AS, 1024 * 1024 * 5)
Process::setrlimit(Process::RLIMIT_CPU, 3)
Process::Sys.setgid(TARGET_GID)
Process::Sys.setuid(TARGET_UID)
Process::exec('/tmp/test')
最后,在我的机器上运行的输出:
$ sudo ./run.rb
[+] uid: 99, gid: 99
[+] trying to allocate 1024 bytes (should succeed)...
[+] success.
[+] trying to allocate 5242880 bytes (should fail)...
[+] ok. now doing infinite loop (should get killed pretty soon)...
$
正如@falsetru所指出的,您希望以其他用户身份运行的系统调用是setrlimit
或从命令行su
或sudo
。
如果要限制资源,则需要使用来自 shell 的setrlimit
系统调用或ulimit
。这将限制内存使用等,但不会限制总运行持续时间 - 您必须跟踪进程并在需要时kill
它。
您还可以查看nice
以设置其优先级。