改变UID和GID
在UNIX系统中,所有的权限都是依赖于UID和GID的。
一般来说应该让程序使用最小权限模型。这可以减少一些安全风险。
可以使用setuid和setgid函数改变实际UID、实际GID、有效UID和有效GID:
#include <unistd.h>
int setuid(uid_t uid);
int setgid(gid_t gid);
|
Both return: 0 if OK, 1 on error |
什么样的用户可以改变ID值:
- 如果进程拥有超级用户的权限
- 如果进程没有超级用户的权限,但uid等于实际UID或saved set-user-ID,那么setuid只能设置有效用户ID到uid。
- 如不是以上两种条件,errno被设置成EPERM,并且返回1。
在这我们假定_POSIX_SAVED_IDS为真,如果不支持这个功能,那么删除之前指向saved set-user-ID的所有索引。
关于内核维护的三种用户ID的说明:
- 只有超级用户进程可以改变实际用户ID,一般来说,实际用户ID被login程序设置,当登路系统后就不再改变。因为login是超级用户进程,所以它可以使用setuid设置三种用户ID
- 当程序文件已经设置了SUID位时,有效用户ID由exec函数设置。如果SUID位没设置,那么有效ID保留当前值。可以随时调用setuid设置有效用户ID为实际用户ID或saved set-user-ID。正常来说不能设置有效用户ID到随机值。
- saved set-user-ID是由exec函数从有效用户ID那里复制来的。如果SUID已经设置,在exec后保存文件的UID到有效用户ID中。
(这里关于saved set-user-ID还是挺复杂的,主要是有一个关于man的例子,还是看APUE的8.11节吧!)
setreuid和setregid函数
历史上,BSD支持使用setreuid函数交换实际UID和有效UID。
#include <unistd.h> int setreuid(uid_t ruid, uid_t euid); int setregid(gid_t rgid, gid_t egid); |
Both return: 0 if OK, 1 on error |
参数设置成1表示保留相应的ID,不做改变。
规则很简单:一个无特权的用户可以交换实际用户ID和有效用户ID。这允许一个设置了SUID的程序交换UID和有效UID并在之后再交换回去。当saved set-user-ID被引入POSIX.1时,这个功能被增强到可以交换有效用户ID和saved set-user-ID。
seteuid和setegid函数
POSIX.1包含了seteuid和setegid两个函数。这两个函数类似于setuid和setgid,但是只能改变有效用户ID和有效用户组ID。
#include <unistd.h>
int seteuid(uid_t uid);
int setegid(gid_t gid);
|
Both return: 0 if OK, 1 on error |
对于无特权用户,该函数可以设置有效用户ID成实际用户ID或它的saved set-user-ID。对于特权用户,有效用户ID只能设置成uid。(它不同于setuid函,setuid可以改变所有三种用户ID——实际用户ID、有效用户ID和saved set-user-ID)
下图汇总了各种改变户用ID函数的功能
