特权(如能改变当前日期的表示法以及访问控制)是基于用户和组ID的,当程序需要增加特权,或需要访问当前并不允许访问的资源时,我们需要更换自己的用户ID或组ID,使得新ID具有合适的特权或访问权限。当程序需要降低其特权或阻止对某些资源的访问时,也需要更换用户ID或组ID,从而使新ID不具有相应特权或访问这些资源的能力。

一般来说我们总是试图使用最小特权(least privilege)。

1 #include <unistd.h>
2 
3 //设置实际和有效用户ID和组ID,若成功则返回0,出错则返回-1
4 int setuid(uid_t uid);
5 
6 int setgid(gid_t gid);

考虑有关改变用户ID的规则:

1、若进程具有超级用户权限,则setuid将实际用户ID、有效用户ID以及保存的设置用户ID设置为uid

2、若进程没有超级用户权限,但是uid等于实际用户ID或保存的设置用户ID,则setuid只将有效用户ID设置为uid,不改变实际用户ID和保存的设置用户ID

3、如果上面两个条件都不满足,则将errno设置为EPERM,并返回-1

关于内核所维护的三个用户ID,还需要注意:

1、只有超级用户进程可以更改实际用户ID

2、仅当对程序文件设置了设置用户ID位时exec才会设置有效用户ID,如果设置用户ID位没有设置,则exec不会改变有效用户ID,任何时候都可以调用setuid将有效用户ID设置为实际用户ID或保存的设置用户ID

3、保存的设置用户ID是由exec复制有效用户ID而得来的。如果设置了文件的设置用户ID位,则在exec根据文件的用户ID设置了进程的有效用户ID以后,就将这个副本保存起来。

 

ID

exec

setuid(uid)

设置用户ID位关闭

设置用户ID位打开

超级用户

非特权用户

实际用户ID

不变

不变

设为uid

不变

有效用户ID

不变

设置为程序文件的用户ID

设为uid

设为uid

保存的设置用户ID

从有效用户ID复制

从有效用户ID复制

设为uid

不变