进程相关联的用户ID

overview

与进程相关联的ID有6个或更多,可以分为三组

  • 实际用户ID
  • 实际组ID

  • 有效用户ID

  • 有效组ID
  • 附加组

  • 保存的设置用户ID

  • 保存的设置组ID

第一组标识着我们究竟是谁,这两个取自登录时的口令文件——即登录用户ID及其组ID;

第二组决定了文件访问权限

第三组是在执行一个程序时由exe函数保存的——有效用户ID的副本

作用

打开一个程序时,为什么要关联这些ID呢?这些和文件的用户ID与组ID有什么关系呢?

通常文件都有一个所有者和组所有者,对应stat结构中的st_uid与st_gid

其实进程相关联的ID,就是和文件相关联的ID来进程配合着进行权限控制——文件相关联的ID标识着哪些用户,哪些组有权限对该文件进行操作;而进程就是操作方。

  • 新建文件

    • 新文件的用户ID就是进程的有效用户ID

    • 组ID可以是进程的有效组ID,也可以是它所在目录的组ID。

  • 操作文件

    • 如果进程的有效用户ID是0(即超级用户),允许任何操作

    • 有效用户ID等于文件的用户ID——所有者对应的访问权限位被设置,则允许相应的操作,否则拒绝

    • 有效用户ID或附加组ID之一等于文件的组ID——检查组适当的访问权限位

    • 文件的其他用户对应的权限位被设置,则允许访问,否则拒绝

关联ID之间的转换

  • 执行一个程序文件时,进程的有效用户ID和组ID通常就是实际用户ID和实际组ID

  • st_mode中有两个特殊标志(set-user-ID、set-group-ID),设置了它们之后,执行一个程序文件,进程的有效用户ID和组ID就变成了文件的用户ID(st_uid)和组ID(st_gid)

保存的设置用户ID的用处

假如当前登录用户是vagrant,程序文件的所有者是root.

默认情况,保存的设置用户ID与有效用户ID是相等的。在未设置S_ISUID位时,进程相关联的用户ID如下:

实际用户ID:vagrant
有效用户ID:vagrant
保存的设置用户ID:vagrant

当设置了S_ISUID位后执行该程序,进程相关联的用户ID如下:

实际用户ID:vagrant
有效用户ID:root
保存的设置用户ID:root

这时进行一些root权限的操作后,通过setuid(getuid())又变回了实际用户:

实际用户ID:vagrant
有效用户ID:vagrant
保存的设置用户ID:root

好了,问题来了,这时我再想变回root用户怎么办?虽然实际用户ID和有效用户ID都已经变成了vagrant,但是设置用户ID还有一个副本被保存到了保存的设置用户ID里了,通过setuid或seteuid即可以恢复。

相关操作

  • 获取set-user-ID与set-group-ID标识
1
2
int set_user_ID = buf.st_mode & S_ISUID;
int set_group_ID = buf.st_mode & S_ISGID;
  • 设置set_user_ID和set_group_ID位
1
2
buf.st_mode = buf.st_mode | S_ISUID;
buf.st_mode = buf.st_mode | S_ISGID;
  • 清除S_ISUID与S_ISGID标识
1
2
buf.st_mode = buf.st_mode & (~S_ISUID);
buf.st_mode = buf.st_mode & (~S_ISGID);
  • 获取实际ID
1
2
uid_t getuid(void);
gid_t getgid(void);
  • 设置实际用户ID与有效用户ID
1
2
int setuid(uid_t uid);
int setgid(gid_t gid);
  • 获取有效用户ID
1
2
uid_t geteuid(void);
gid_t getegid(void);
  • 设置有效用户ID
1
2
int seteuid(uid_t uid);
int setegid(gid_t gid);

参考资料

  1. APUE 4.4、4.5、8.2、8.11

  2. S_ISUID、S_ISGID位与文件访问权限检查

  3. linux中用st_mode判断文件类型

  4. Linux进程相关ID—有效用户ID 实际用户ID 保存设置用户ID

坚持原创技术分享,您的支持将鼓励我继续创作!