改变UID和GID

改变UID和GID

在UNIX系统中,所有的权限都是依赖于UID和GID的。

一般来说应该让程序使用最小权限模型。这可以减少一些安全风险。

可以使用setuidsetgid函数改变实际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值:

  1. 如果进程拥有超级用户的权限
  2. 如果进程没有超级用户的权限,但uid等于实际UID或saved set-user-ID,那么setuid只能设置有效用户ID到uid
  3. 如不是以上两种条件,errno被设置成EPERM,并且返回1。

在这我们假定_POSIX_SAVED_IDS为真,如果不支持这个功能,那么删除之前指向saved set-user-ID的所有索引。

关于内核维护的三种用户ID的说明:

  1. 只有超级用户进程可以改变实际用户ID,一般来说,实际用户ID被login程序设置,当登路系统后就不再改变。因为login是超级用户进程,所以它可以使用setuid设置三种用户ID
  2. 当程序文件已经设置了SUID位时,有效用户ID由exec函数设置。如果SUID位没设置,那么有效ID保留当前值。可以随时调用setuid设置有效用户ID为实际用户ID或saved set-user-ID。正常来说不能设置有效用户ID到随机值。
  3. saved set-user-ID是由exec函数从有效用户ID那里复制来的。如果SUID已经设置,在exec后保存文件的UID到有效用户ID中。

(这里关于saved set-user-ID还是挺复杂的,主要是有一个关于man的例子,还是看APUE的8.11节吧!)

setreuidsetregid函数

历史上,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。

seteuidsetegid函数

POSIX.1包含了seteuidsetegid两个函数。这两个函数类似于setuidsetgid,但是只能改变有效用户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函数的功能

Summary of all the functions that set the various user IDs
Summary of all the functions that set the various user IDs
Comments are closed.