首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >RealUID,保存的UID,有效的UID。到底怎么回事?

RealUID,保存的UID,有效的UID。到底怎么回事?
EN

Stack Overflow用户
提问于 2011-12-14 11:53:15
回答 3查看 31.3K关注 0票数 39

这是一个set-root-uid程序

代码语言:javascript
运行
复制
$ls -l
-rwsr-sr-x 1 root root 7406 2011-12-13 22:37 ./x*

源码:

代码语言:javascript
运行
复制
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 ;       
}

输出

代码语言:javascript
运行
复制
         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  

我的问题

手册页说明setuid将更改真实的、已保存的和有效的uid。因此,在调用setuid(1000)之后,这三个函数都更改为1000。让我把euid改成0setuid(0)怎么样?

EN

回答 3

Stack Overflow用户

发布于 2011-12-14 12:01:43

DESCRIPTION setuid()设置调用进程的有效用户ID。如果调用者的有效UID是root,则还会设置真实的UID和保存的set-user-ID。

在Linux下,setuid()的实现类似于具有_POSIX_SAVED_IDS特性的POSIX版本。这允许set- user -ID (而不是root)程序删除它的所有用户特权,执行一些非特权的工作,然后以安全的方式重新使用原始的有效用户ID。

如果用户是root,或者程序是set- user -ID-root,则必须特别小心。setuid()函数检查调用者的有效用户ID,如果是超级用户,则将所有与进程相关的用户ID设置为uid。发生这种情况后,程序不可能重新获得root权限。

因此,如果set- user -ID-root程序希望暂时删除root权限,使用非特权用户的身份,然后重新获得root权限,则不能使用setuid()。您可以使用seteuid(2)来完成此操作。

(摘自Linux程序员手册,2014-09-21,第setuid.2页)

票数 10
EN

Stack Overflow用户

发布于 2011-12-14 13:19:06

不是的!这些函数很难正确使用。

手册页说明setuid将更改真实的、已保存的和有效的uid。因此,在调用setuid( 1000 )之后,这三个参数都更改为1000。

当且仅当您是euid 0时,才会出现这种情况。然而,在调用setuid(0)时,您是EUID1000并且保存了uid0(例如,检查getresuid(2) )。这就是为什么你能够重新获得特权。

票数 5
EN

Stack Overflow用户

发布于 2019-04-11 01:00:32

代码:

代码语言:javascript
运行
复制
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>

void print_uid(char *str, int ret)
{
    uid_t ruid;
    uid_t euid;
    uid_t suid;
    getresuid(&ruid, &euid, &suid);

    printf("%s ret:%d\n"
           "Real:%4d  Effective:%4d  Saved:%4d\n",
           str, ret, ruid, euid, suid);
}

int main(void)
{
    int ret = 0;
    print_uid("init", ret);            /* Real:1000  Effective:   0  Saved:   0 */

    ret = seteuid(600);
    print_uid("seteuid(600)", ret);    /* Real:1000  Effective: 600  Saved:   0 */

    ret = setuid(1000);
    print_uid("setuid(1000)", ret);    /* Real:1000  Effective:1000  Saved:   0 */

    ret = setuid(0);
    print_uid("setuid(0)", ret);       /* Real:1000  Effective:   0  Saved:   0 */

    ret = setuid(1000);
    print_uid("setuid(1000)", ret);    /* Real:1000  Effective:1000  Saved:1000 */

    ret = setuid(0);
    print_uid("setuid(0)", ret);       /* Real:1000  Effective:1000  Saved:1000 */

    return 0 ;       
}

sudo chown root setuid_feature

sudo chmod +s setuid_feature

Linux中的进程有三个uid :真正的uid、有效的uid和保存的uid。

条件1.当euid为root时,setuid或seteuid可以设置为任何uid,但有一个副作用,当使用setuid(不是seteuid)时,这三个都可以设置为不是ROOT的同一uid,这样进程就无法重新获得ROOT权限。

条件2.当euid不是root时,setuid或seteuid可以设置为ruid或suid,并且只更改euid。

代码语言:javascript
运行
复制
                       |      seteuid             |          setuid  
Cond 1. (euid == root) | set euid to any uid      | set all three uids to any uid  
Cond 2. (euid != root) | set euid to ruid or suid | set euid to ruid or suid  

因此,代码中有5个setuid或seteuid进程,让我对它们进行分类:

  1. setuid(600):Cond 1,将euid设置为600
  2. setuid(1000):Cond 2,将euid设置为1000
  3. setuid(0):Cond 2,将euid设置为0(suid)
  4. setuid(1000):Cond 1,将所有三个euid设置为1000
  5. setuid(0):Cond 2,所有三个euid都不等于0,因此不能设置为0,失败,返回ret = -1
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8499296

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档