每个进程都有一套用数字表示的用户ID(UID)和组ID(GID)。有时,也将这些ID诚挚为进程凭证
实际用户id和实际组id
实际用户id和实际组id确定了进程所属的用户和组。作为登录过程的步骤之一,登录shell从/etc/passwd文件中读取相应用户密码记录的第三字段和第四字段,设置为实际用户id和实际组id。当创建进程时,将从其父进程中继承这些ID
有效用户ID和有效组ID
在大多数UNIX实现中,当进程尝试执行各种操作时,将结合有效用户ID、有效组ID、连通辅助组ID一起来确定授予进程的权限。有效用户ID为0的进程拥有超集用户的所有权限。通常有效用户id以及有效组id与其实际的ID相等,但是有两种方法能够使得二者不同。其一是之后要说明的系统调用,其二是执行set-user-id和set-group-ID程序
set-user-ID和set-group-ID程序
set-user-ID程序会将进程的有效用户id设置为可执行文件的用户id(属主),从而获得常规情况下并不具有的权限。set-group-ID程序对进程有效组id实现类似任务
保存set-user-ID和保存set-group-ID
设计保存set-user-ID和保存set-group-ID,意在与set-user-ID和set-group-ID程序结合使用。当执行程序时,会发生如下事件:
1. 若可执行文件的set-user-ID(set-group-ID)权限已经开启,则将进程的有效用户(组)id置为可执行文件的属主,若未设置set-user-ID(set-group-ID)权限位,则进程的有效用户(组)ID将保持不变
2. 保存set-user-ID和保存set-group-ID的值由对应的有效id复制而来。无论正在执行的文件是否设置了set-user-ID或set-group-ID权限位,这一复制都将进行。
有不少系统调用,允许将set-user-ID程序的有效用户id在实际用户id和保存set-user-ID之间切换
文件系统用户id和组id
在linux系统中,如果要进行诸如打开文件、改变文件属主、修改文件权限之类的文件系统操作时,决定其操作权限的是文件系统用户id和组id(结合辅助组ID),而非有效用户id和组ID
通常,文件系统用户id和组id的值等同于相应的有效用户id和组id。此外,只要有效用户或组id发生了变化,无论是通过系统调用韩式通过执行set-user-ID或者set-group-ID程序,则相应的文件系统id也将随之改变为同一值。只有当使用linux特有的两个系统调用(setfsuid()和setfsgid())时,才能刻意制造出文件系统id与相应有效id的不同
辅助组ID
辅助组id用于标识进程所属的若干附加的组,新进程从其父进程处继承这些id,登录shell从系统组文件中获取其辅助组的组id。这些id与有效id以及文件系统id相结合,就能决定对文件、system V IPC对象和其他系统资源的访问权
获取和修改进程凭证的相关系统调用如下:
-
#include <unistd.h>
-
uid_t getuid(void);
-
/*returns real user ID of calling process*/
-
uid_t geteuid(void);
-
/*returns effective user ID of calling process*/
-
uid_t getgid(void);
-
/*returns real group ID of calling process*/
-
uid_t getegid(void);
-
/*returns effective group ID of calling process*/
-
int setuid(uid_t uid);
-
/*returns 0 on success, or -1 on error*/
-
int setgid(gid_t gid);
-
/*returns 0 on success, or -1 on error*/
当进程使用setuid()和setgid()系统调用规则如下:
1. 当非特权进程调用setuid(),仅能修改进程的有效用户id,而且仅能将有效用户id修改成相应的实际用户id或保存set-user-ID
2. 当特权进程一亿个非0参数调用setuid()时,实际用户id、有效用户id、保存set-user-ID均被置为uid指定的值。这一操作是单向的。
-
#include <unistd.h>
-
int seteuid(uid_t euid);
-
int setegid(gid_t egid);
-
/*both return 0 on success, or -1 on error*/
进程使用上述两个函数修改有效id时,会遵循以下规则:
1. 非特权级进程仅能将其有效id修改为相应的实际id或者保存set-xxx-ID
2. 特权级进程能够将其有效id修改为人一直。若修改为非0,那么此进程不再具有特权,可以改回来
-
#include <unistd.h>
-
int setreuid(uid_t ruid, uid_t euid);
-
int setregid(gid_t rgid, gid_t egid);
-
/*both return 0 on success, or -1 on error,若只想修改一个,另一个设置为-1 即可*/
上述两个系统调用在使用时,遵循规则如下:
1. 非特权进程只能将其实际用户id设置为当前实际用户id或有效用户id,且只能将有效用户id设置为当前实际用户id、有效用户id、或保存set-user-ID
2. 特权级进程能够设置其实际用户id和有效用户id为任意值
3. 不管进程拥有特权与否,只要如下条件之一成立,就能将保存set-user-ID设置成新的有效用户id
ruid不为-1
对有效用户id所设置的值不同于系统调用之前的实际用户id
-
#define _GNU_SOURCE
-
#include <unistd.h>
-
int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
-
int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
-
/*both return 0 on success, or -1 on error*/
-
-
#define _GNU_SOURCE
-
#include <unistd.h>
-
int setresuid(uid_t ruid, uid_t euid, uid_t suid);
-
int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
-
/*both return 0 on success, or -1 on error*/
若不想同时修改这些id,只需要将无意修改的id参数指定为-1即可。遵循规则如下:
1. 非特权进程只能够将实际用户id、有效用户id、保存id中的任意id设置为实际用户id、有效用户id或保存id之中的任一当前值
2. 特权级进程能够对其实际用户id、有效用户id和保存id做任意设置
3. 不管系统调用是否对其他id做了任何改动,总是将文件系统用户id设置为与有效用户id相同
阅读(1320) | 评论(0) | 转发(0) |