即使我不是超级用户,如何为 Nice() 提供负值并运行而不会出现错误

即使我不是超级用户,如何为 Nice() 提供负值并运行而不会出现错误

即使我不是超级用户,如何为 Nice() 提供负值并运行而不会出现错误,我可以吗

system("su"); 
nice(-1);

它要求输入我不想要的密码?

答案1

如果您拨打电话su,系统将要求您输入密码,除非您是 root 用户。

为了能够重新处理负值,该过程需要:

答案2

你不能。这就是系统的重点。普通用户不得提高其任务的优先级。

答案3

进程无法提升自己的权限。

进程绝对没有办法提升其权限。如果可以的话它就已经拥有它们了。

如果一个进程有真实的或保存的uid提升,那么它可以将该uid复制到有效uid中;如果它具有允许的功能,那么它可以将这些功能复制到有效集中,但它必须首先具有这些权限。你不能凭空对它们施魔法(一把可以随意创造一把钥匙的锁有什么用)。

那么如何在 Unix(包括 Gnu/Linux)中提升权限呢?

(请小心,仅适用于专家)

有两种方法(传统的一种,但它们都很相似,而且原来的方法可能有一天会消失)。对于这两种情况,当您调用 exec 时都会发生这种情况。 (好吧,我在上面撒了谎,因为运行 exec 后我们处于同一进程中,权限已更改,但正在运行新代码)。

  • 设置可执行文件的 setuid 和/或 setuid 位:当文件被exec编辑时,用户 ID 和/或组 ID 将更改为文件的用户 ID 和/或组 ID(可能是 root)(这不适用于大多数 Unix 上的脚本语言) )。
  • 设置可执行文件的功能位:当文件被exec编辑时,进程将获得文件中设置的功能。这就是现在的推荐方法。
    • 如果您要将 seduid 根程序转换为功能,则可以根据需要设置允许的功能,并设置有效位(这会将所有允许的功能复制为有效)。
    • 当您编写新程序时,它可以感知功能,因此最好不要设置有效位,您的程序可以根据需要复制和清除有效功能(这可以减少错误(包括漏洞利用)的影响)。

例子:

//renice.cc
#include <unistd.h>
#include <sys/capability.h>

class Renice {
  cap_t original_cap_state;
  cap_t can_nice_cap_state;
  cap_value_t cap_list[1];

public:
    Renice() {
    original_cap_state = cap_get_proc();
    if ( original_cap_state == NULL)
      /* handle error */;
    can_nice_cap_state = cap_get_proc();
    if ( can_nice_cap_state == NULL)
      /* handle error */;
    cap_list[0] = CAP_SYS_NICE;
    if (cap_set_flag(can_nice_cap_state, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1)
      /* handle error */;
  }

  ~Renice() {
    if (cap_free(original_cap_state) == -1 )
      /* handle error */;
  }

  void new_value(int v) {
    if (cap_set_proc(can_nice_cap_state) == -1)
      /* handle error */;

    nice (v);
    /* handle error */

    if (cap_set_proc(original_cap_state) == -1)
      /* handle error */;
  }
};

int main () {
  Renice renice;
  renice.new_value(-1);
  nice (-2); //won't work, capability no longer set
  sleep (30);
}
  • 编译:g++ -lcap renice.cc
  • 设置功能:sudo setcap CAP_SYS_NICE+p a.out
  • 运行:./a.out

相关内容