【问题标题】:How to limit program runtime, memory usage and as a specific user programmatically in Linux如何在 Linux 中以编程方式限制程序运行时、内存使用和作为特定用户
【发布时间】:2014-02-09 13:11:41
【问题描述】:

是否有一种编程方式来限制持续时间、内存使用并作为在 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

这两个语句都使该命令以与执行程序相同的用户身份运行,并根据需要使用整个处理能力和内存。

【问题讨论】:

    标签: c ruby cpu-usage memory-limit least-privilege


    【解决方案1】:

    使用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
    

    【讨论】:

      【解决方案2】:

      您需要使用 setrlimit 系统调用来限制内存 (Process::RLIMIT_AS)。要限制程序的运行时间,您只能控制进程获得 CPU 时间的总秒数(因此这不考虑睡眠或等待 I/O 所花费的时间)。这是通过Process::CPU 完成的。

      使用Process::Sys.setgid 删除权限,然后使用Process::Sys.setuid 设置这些 rlimits,但在使用Process::exec 调用目标进程之前。

      示例目标程序:

      #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: %d\n", 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)...
      $
      

      【讨论】:

        【解决方案3】:

        正如@falsetru 所说,您想以其他用户身份运行的系统调用是setrlimit 或来自命令行susudo

        如果你想限制资源,你想使用setrlimit系统调用或来自shell的ulimit。这将限制内存使用等,但不会限制总运行持续时间 - 如果需要,您必须跟踪进程并 kill 它。

        您也可以查看nice 来设置其优先级。

        【讨论】:

          猜你喜欢
          • 2017-10-16
          • 2016-05-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-18
          • 1970-01-01
          • 2010-12-28
          相关资源
          最近更新 更多