多进程编程之用户ID和用户组ID
实际用户ID(real user id):用于在系统中标识一个用户是谁,当用户使用用户名和密码成功登录后一个UNIX系统后就唯一确定了他的uid;(实际用户组ID类似)
有效用户ID(effective user id):用于系统决定用户对系统资源的权限,一般情况下,进程的有效用户ID就被设成执行该进程的实际用户ID,有效用户组ID=实际用户组ID;还有一种说法是有效用户ID指的是进程执行时对文件的访问权限,应该意思都是一样的,因为进程和用户都有实际用户ID、有效用户ID、实际用户组ID、有效用户组ID,查看用户相关的一些ID时使用id命令,具体使用查看id --help;
保存设置用户ID(saved set-user-id):是有效用户ID的副本,为了调用exec之后恢复原来的有效用户ID;
设置用户ID位(set-user-id):设置用户ID,这是相对于文件来说的.设置了set-user-ID位的可执行程序,执行时,进程的effective user ID与saved set-uesr-ID都为程序文件所属用户的ID,这时real user ID与effective user ID就不一定相等了.这类程序称之为SUID程序,这类程序有特殊的用途.典型的例子:passwd程序,ping程序等.passwd程序是要修改用户密码,此时是要修改/etc/passwd或修改/etc/shadow文件(有必要时),然而一般用户没有修改这两个文件的权限.passwd程序设置了set-user-ID位,并且该程序的所有者是root,所以,一般用户执行时,也具有了root的权限.
1 [root@246 ~]# cd /usr/bin/ 2 [root@246 bin]# ls -l passwd 3 -rwsr-xr-x 1 root root 25700 2008-04-08 21:48 passwd 4 [root@246 bin]# 5 6 /*第4位的s就是设置用户id位*/
首先我们看下命令执行的过程,当普通用户执行passwd命令时,shell会fork出一个子进程,此时子进程有效用户ID还是普通用户ID,然后exec程序执行/usr/bin/passwd。通过上面的表我们会知道,exec发现/usr/bin/passwd有SUID位,于是会把子进程的有效用户ID设成设置成pssswd文件用户ID,显然就是root, 此时这个进程都获得了root权限, 得到了读写/etc/shadow文件的权限, 从而普通用户可完成密码的修改。exec进程退出后会恢复普通用户的EUID为普通用户ID.这样就不会使普通用户一直拥有root权限。
在UNIX系统中,特权以及访问控制,是基于用户ID和组ID的。当程序需要增加特权或需要访问当前并不允许访问的资源时,我们需要更换自己的用户ID或组ID,使得新的ID具有合适的特权或访问权限。可以使用setuid函数设置实际用户ID和有效用户ID,可以用setgid函数设置实际组ID和有效组ID。
1 #include <unistd.h> 2 3 int setuid(uid_t uid); 4 5 int setgid(gid_t gid); 6 7 //两个函数返回值:若成功,返回0;若出错,返回-1;
谁能更改ID有若干规则:
1)若进程具有超级用户特权,则setuid函数将实际用户ID、有效用户ID以及保存的设置用户ID设置为uid;
2)若进程没有超级用户特权,但是uid等于实际用户ID或保存的设置用户ID,则setuid只将有效用户ID设置为uid,不能更改实际用户ID和保存的设置用户ID;
3)如果上面的两个条件都不满足,则errno设置为EPERM,并返回-1;(errno 是记录系统的最后一次错误代码,EPERM表示没有执行权限)