【Linux学习笔记】4. 进程的用户/组id

# 进程的用户/组id

如果进程的三个用户/组ID的概念都已经了解过但还是无法理解的,可以直接看最下面的案例分析


# 进程的三个用户/组ID
  • real id
  • effective id
  • saved id

由于分析用户uid和组gid比较类似,方便起见,下面只分析了用户uid的情况,使用统称如real user id和real group id统一写作real id。

# real id

real user id是真正执行process起来的用户user
进程是由哪个用户调用的,或者是由哪个父进程发起的,就是进程的real id。

# effective id

effective id的作用主要是决定文件的访问权限。这个id的情况比较复杂。

  • 一般情况下,没有设置set-user-ID位时,effective id会等于real id
  • set-user-IDbit = ON时,effective id等于该文件的owner id

关于owner id:在系统中每个文件都有一个owner和group owner,这一般是通过stat结构中的st_uid来标记的。
关于set-user-id:在文件的mode里面有个叫做set-user-id的位,在设置了该位后,程序运行的时候effective-user-id等于该文件的owner id。作用就是其他用户可以像owner一样运行该程序。

# saved id

saved id仅在effective id发生改变时由exec系统调用保存。

当进程没有root权限的时候,进程在设置effective id时需要将设置的id和real id或者saved id进行比较,并且只能设置为其中的一个。

也就是说,saved id的主要作用是在进程切换effective id时的可选项。

没有任何的api可以获取到saved id,这个id完全由内核管理,仅在系统调用setuid()时起作用。

# 案例1

系统中有两个用户A和B

B创建一个可执行程序proc,并且设置set-user-idbit

A执行proc时,proc进程的用户id如下:

  • real id = A
  • effective id = B
  • saved id = B

因为proc由A执行,因此real id = A。proc的set-user-id被置位,因此effective id = owner id = B。而saved id = effective id。

此时进程执行对B具有的权限相应的操作。当程序将effective id设置回A。此时用户id如下:

  • real id = A
  • effective id = A
  • saved id = B

因为A是real id,因此改动成功。

# 案例2

用户A创建了一个main程序,此时main的owner id = A。
当以A用户的身份直接运行main时:

  • real id = A
  • effective id = A
  • saved id = A

当以root用户执行main时:

  • real id = 0
  • effective id = 0
  • saved id = 0

因为没有设置set-user-id位,因此effective id总是与real id一致。

使用chown B命令修改owner id = B。 继续以A的身份运行main:

  • real id = A
  • effective id = A
  • saved id = A

原因和上面一样,虽然文件的owner已经改成B了,但是没设置set-user-id位,因此effective id还是等于real id

使用chmod u+s命令设置set-user-id位为ON。 继续以A的身份运行main:

  • real id = A
  • effective id = B
  • saved id = B

因为set-user-id位打开,effective id = owner id,由于前面使用了chown命令将owner id改为了B,因此effective id = B。
而上面所有的saved id都与effective id一致。这个id的设置完全由内核控制,程序员无法获取到该id的信息。

# setuid()系统调用

setuid(uid)首先请求内核将本进程的[real id],[effective id]和[saved id]设置成函数指定的uid, 若权限不够则请求将effective uid设置成uid, 再不行则调用失败。

分两种情况讨论:

  • 进程当前的effective id = 0(root):setuid(uid)会同时把real id、effective id、saved id设置为uid
  • 进程当前的effective id = 普通用户:setuid(uid)只有当uid为real id或saved id中的一个才能调用成功,结果就是把effective id设置成两者之一。若参数uid是其他值,则setuid()调用将返回错误。

因此,非root用户是不可能通过setuid()或者seteuid()取得其他权限(包括root权限)的,它只能恢复原来的权限。只能通过exec一个设置了set-user-id位的可执行程序,来取得其他(程序文件所有者)权限(包括root权限)。

关于sudo

sudo的实现里有setuid函数,通过setuid()将进程的real UID和effective UID都设置为了0,因此整个过程中进程都是有root权限的。

# seteuid()系统调用

主要讨论与setuid()的区别。

  • setuid(uid)首先请求内核将本进程的[real id],[effective id]和[saved id]设置成函数指定的uid, 若权限不够则请求将effective uid设置成uid, 再不行则调用失败.
  • seteuid(uid)仅请求内核将本进程的[effective id]设置成函数指定的uid.

对于非root用户来说,setuid()和seteuid()的行为是完全一样的。

对于root用户来说,setuid()可以设置real id、effective id、saved id三个id,而seteuid()只会设置effective id,并且与setuid()一样,只能将其设置为real id或saved id其中一个,因为非root用户是不可能通过setuid()或者seteuid()取得其他权限(包括root权限)的,它只能恢复原来的权限。

参考:https://blog.csdn.net/todd911/article/details/7738069
修改时间:2022.03.29

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值