这是一个设置根uid程序

$ls -l
-rwsr-sr-x 1 root root 7406 2011-12-13 22:37 ./x*

The source code:

int main(void) {
    printf(
        "         UID           GID  \n"
        "Real      %d  Real      %d  \n"
        "Effective %d  Effective %d  \n",
             getuid (),     getgid (),
             geteuid(),     getegid()
    );

seteuid(600);
    printf(
        "         UID           GID  \n"
        "Real      %d  Real      %d  \n"
        "Effective %d  Effective %d  \n",
             getuid (),     getgid (),
             geteuid(),     getegid()
    );

setuid(1000);

    printf(
        "         UID           GID  \n"
        "Real      %d  Real      %d  \n"
        "Effective %d  Effective %d  \n",
             getuid (),     getgid (),
             geteuid(),     getegid()
    );

setuid(0); // HOW DOES THIS SUCCEED IN SETTING THE EUID BACK TO 0
    printf(
        "         UID           GID  \n"
        "Real      %d  Real      %d  \n"
        "Effective %d  Effective %d  \n",
             getuid (),     getgid (),
             geteuid(),     getegid()
    );

    return 0 ;       
}

OUTPUT

         UID           GID  
Real      1000  Real      1000  
Effective 0  Effective 0  
         UID           GID  
Real      1000  Real      1000  
Effective 600  Effective 0  
         UID           GID  
Real      1000  Real      1000  
Effective 1000  Effective 1000  
         UID           GID  
Real      1000  Real      1000  
Effective 0  Effective 1000  

My question

手册页声明setuid将更改真实、已保存和有效的uid.

推荐答案

有两种情况,

  1. 您想在执行setuid程序时暂时删除root权限
  2. 您想在执行setuid程序时永久删除root权限...
  • 您可以通过将euid设置为真实用户id,然后将uid更改为您想要的任何内容来临时执行此操作.稍后,当您需要恢复root权限时,可以将uid设置为root,有效的userid将更改为root.这是因为保存的用户id没有更改.
  • 通过直接将uid更改为权限较低的用户id,可以永久删除权限.之后,无论发生什么,都无法恢复根权限.

case 1:

在setuid程序开始执行后

1.seteuid(600);
2.setuid(1000);
3.setuid(0);

在这种情况下,根权限可以再次获得.

              +----+------+------------+
              | uid|euid  |saved-uid   |
              |----|------|------------|
            1.|1000| 0    | 0          |
            2.|1000| 600  | 0          |
            3.|1000| 1000 | 0          |
            4.|1000|  0   | 0          |
              |    |      |            |
              +------------------------+

case 2:

在setuid程序开始执行后

1.setuid(1000);
2.setuid(0);



               +----+------+------------+
               | uid|euid  |saved-uid   |
               |----|------|------------|
             1.|1000|0     | 0          |
             2.|1000|1000  | 1000       |
               |    |      |            |
               +------------------------+

在这种情况下,您无法获得root权限.

cat/proc/PROCID/task/PROCID/status | less

Uid:    1000    0       0       0
Gid:    1000    0       0       0

这个命令将显示Uid和Gid,它将有4个字段(前三个字段是我们关注的字段).类似上面的东西

The three fields represent uid,euid and saved-user-id. You can introduce a pause (an input from user) in your setuid program and check for each step the cat/proc/PROCID/task/PROCID/status | less command. During each step you can check the saved uid getting changed as mentioned.

If you're euid is root and you change the uid, the privileges gets dropped permanently.If effective user id is not root then saved user id is never touched and you can regain the root privilege back anytime you want in your program.

Linux相关问答推荐

抛出主,即未捕获到SIGSEGV中的异常结果

使用sed或awk映射自定义和任意函数

如何修复 script(1) 实用程序输出的换行符?

在不编写任何代码的情况下,是否有一个命令可以检索当前 shell 的亲和力中的可用内核数?

在 Ubuntu 中,如何设置 Tomcat 9 以使用 Java 17?

c++进程状态中的+是什么意思

将行转换为一条

我需要制作一个 awk 脚本来解析文件中的文本.我不确定我是否做得正确

你如何在 CentOS9 上使用 C++ fmt?

如何重新安装最新的 cmake 版本?

PHP factor 30 从 Linux 到 Windows 的性能差异

Linux/Unix 手册页语法约定

在 Bash 中从最后到第一个输出文件行

sed: -i 不能与 Mac OS X 上的标准输入一起使用

argv的编码是什么?

何时判断 EINTR 并重复函数调用?

rename() 是原子的吗?

Linux SCHED_OTHER、SCHED_FIFO 和 SCHED_RR - 区别

区分 Java 线程和 OS 线程?

如何在 Linux 中将 .so 文件添加到 java.library.path