ulimit - 如何使用 setuid 或功能 CAP_SYS_RESOURCE 以编程方式提高实时优先级的 ulimit 硬限制?

标签 ulimit linux-capabilities

我想在linux SCHED_FIFO实时类下运行一个程序。我更愿意将用户的 RTPRIO 硬限制设置为 0,并以编程方式提高单个进程的硬限制。人们普遍认为,如果我授予进程 CAP_SYS_RESOURCE 允许它提高硬限制,例如, man setrlimit 2 :

The soft limit is the value that the kernel enforces for the corresponding resource. The hard limit acts as a ceiling for the soft limit: an unprivileged process may only set its soft limit to a value in the range from 0 up to the hard limit, and (irreversibly) lower its hard limit. A privileged process (under Linux: one with the CAP_SYS_RESOURCE capability) may make arbitrary changes to either limit value.

但是,我似乎无法让它为我工作。测试代码如下:

#include <stdio.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
#include <sys/resource.h>

#define PRIORITY (50)

int main(int argc, char **argv) {
  struct sched_param param;
  struct rlimit rl;
  int e, min_fifo, max_fifo;

  min_fifo = sched_get_priority_min(SCHED_FIFO);
  max_fifo = sched_get_priority_max(SCHED_FIFO);
  printf("For policy SCHED_FIFO min priority is %d, max is %d.\n",
         min_fifo, max_fifo);
  if ((min_fifo>PRIORITY)||(max_fifo<PRIORITY)) {
    printf("Desired priority of %d is out of range.\n", PRIORITY);
    return 1;
  }

  if (getrlimit(RLIMIT_RTPRIO, &rl) != 0) {
    e = errno;
    printf("Failed to getrlimit(): %s.\n", strerror(e));
    return 1;
  }
  printf("RTPRIO soft limit is %d, hard is %d.\n", 
         (int) rl.rlim_cur, (int) rl.rlim_max);

  // Adjust hard limit if necessary

  if (rl.rlim_max < PRIORITY) {
    rl.rlim_max = PRIORITY;
    if (setrlimit(RLIMIT_RTPRIO, &rl) != 0) {
      e = errno;
      printf("Failed to raise hard limit for RTPRIO to %d: %s.\n", 
             (int) rl.rlim_max, strerror(e));
      return 1;
    }
    printf("Raised hard limit for RTPRIO to %d.\n", (int) rl.rlim_max);
  }

  // Adjust soft limit if necessary

  if (rl.rlim_cur < PRIORITY) {
    rl.rlim_cur = PRIORITY;
    if (setrlimit(RLIMIT_RTPRIO, &rl) != 0) {
      e = errno;
      printf("Failed to raise soft limit for RTPRIO to %d: %s.\n", 
             (int) rl.rlim_cur, strerror(e));
      return 1;
    }
    printf("Raised soft limit for RTPRIO to %d.\n", (int) rl.rlim_cur);
  }

  // Set desired priority with class SCHED_FIFO

  param.sched_priority = PRIORITY;
  if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
    e = errno;
    printf("Setting policy failed: %s.\n", strerror(e));
    return 1;
  } else {
    printf("Set policy SCHED_FIFO, priority %d.\n", param.sched_priority);
  }

  return 0;
}

这可以按预期工作,无需特殊权限,硬限制为 99:

$ ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 99.
Raised soft limit for RTPRIO to 50.
Set policy SCHED_FIFO, priority 50.
$

使用 sudo 可以按预期工作,硬限制为 0:

$ sudo ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 0.
Raised hard limit for RTPRIO to 50.
Raised soft limit for RTPRIO to 50.
Set policy SCHED_FIFO, priority 50.
$

但是,当 setuid root 时,它无法按预期工作:

$ sudo chown root ./rtprio
$ sudo chgrp root ./rtprio
$ sudo chmod ug+s ./rtprio
$ ls -l ./rtprio
-rwsrwsr-x 1 root root 8948 11月 28 12:04 ./rtprio
$ ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 0.
Failed to raise hard limit for RTPRIO to 50: Operation not permitted.

CAP_SYS_RESOURCE 功能以及所有功能也会意外失败:

$ sudo setcap cap_sys_resource=eip ./rtprio
$ getcap ./rtprio
./rtprio = cap_sys_resource+eip
$ ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 0.
Failed to raise hard limit for RTPRIO to 50: Operation not permitted.

$ sudo setcap all=eip ./rtprio
$ getcap ./rtprio
./rtprio =eip
$ ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 0.
Failed to raise hard limit for RTPRIO to 50: Operation not permitted.

我在这里缺少什么?

$ uname -srv
Linux 3.13.0-100-generic #147-Ubuntu SMP Tue Oct 18 16:48:51 UTC 2016
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.5 LTS
Release:    14.04
Codename:   trusty
$ bash --version | head -1
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)

最佳答案

setuid root 不起作用的事实就是线索。

事实证明,上面的测试程序位于使用nosuid挂载的分区中,因此setuid位不起作用。如果您不信任分区中的 setuid 位,那么您可能也不应该信任文件功能。事实上,事实证明,当使用 nosuid 挂载时,文件功能也会被忽略。

看来 luks 加密的主目录倾向于挂载 nosuid

我之所以留下这个问题,是因为有很多搜索引擎点击“linux features nosuid”,这表明在这个问题上浪费了很多时间(但当然你不知道搜索这个直到你弄清楚)。

关于ulimit - 如何使用 setuid 或功能 CAP_SYS_RESOURCE 以编程方式提高实时优先级的 ulimit 硬限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40837181/

相关文章:

c++ - 如何使用 C/C++ 通过 system() 系统调用以外的其他方法获取 Linux 中的文件功能?

Docker-Compose:cap_drop 和 cap_add 的顺序?

centos 不能用 ulimit coredump -c 是无限的

linux - ulimit -Hn的限制

c - msgsnd 无权限错误

linux - setuid(0) 与 CAP_SETUID

linux - 为什么CapEff在/proc/$PID/status中全为零

node.js - 错误 : EMFILE: too many open files, watch ,除非我使用 sudo

linux - 如何增加 Torque 作业的 OpenFabrics 内存限制?

linux - 将进程可以打开的文件数量提高到 2^20 以上