文件模式字中有两个特殊标识:“设置用户ID” 和 “设置组ID”.
“设置用户ID”的作用是“当执行此文件时,将进程的有效用户ID设置为文件所有者的用户ID”
<span style="font-family: Arial, Helvetica, sans-serif;">如 passwd 程序,</span>
<span style="font-family: Arial, Helvetica, sans-serif;">[root@licchen-test-dev001-bjdxt tests]# which passwd</span>
/usr/bin/passwd
[root@licchen-test-dev001-bjdxt tests]# ll /usr/bin/passwd
-rwsr-xr-x 1 root root 30768 Feb 17 2012 /usr/bin/passwd
其权限为:
-rwsr-xr-x
其中 rws 中的 s 代表设置了“设置用户ID”
passwd 程序会更新口令文件(通常是/etc/passwd)
[root@licchen-test-dev001-bjdxt tests]# ll /etc/passwd
-rw-r--r-- 1 root root 1926 Apr 24 20:09 /etc/passwd
/etc/passwd文件的user是root,其只有 root 有权限。
但是passwd进程希望任何一个程序都可以改变自己的口令,所以设置了“设置用户ID”,
这样普通用户在执行passwd程序时,进程的有效用户ID就是passwd程序所有者的用户ID(即root),
root是有权限对 /etc/passwd 进行写操作的。
下面是测试程序:
test_set_uid.cpp
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fstream>
#include <iostream>
#include <exception>
#include <stdlib.h>
using namespace std;
int main(int argc, char** argv) {
if (argc != 2) {
exit(0);
}
fstream fs;
try {
fs.open("/root/lic_test", fstream::in | fstream::out | fstream::app);
} catch(exception) {
cout << "open lic_test error." << endl;
}
fs << argv[1] << endl;
}
[root@licchen-test-dev001-bjdxt tests]# g++ -o test_set_uid test_set_uid.cpp
[root@licchen-test-dev001-bjdxt tests]# touch /root/lic_test
[root@licchen-test-dev001-bjdxt tests]# cat /root/lic_test
[root@licchen-test-dev001-bjdxt tests]# cat /root/lic_test
[root@licchen-test-dev001-bjdxt tests]# ./test_set_uid from_root
[root@licchen-test-dev001-bjdxt tests]# cat /root/lic_test
from_root
因为当前为 root 的 home,其他用户没有权限访问该文件夹,将进程放到其他用户可以访问的文件夹。
[root@licchen-test-dev001-bjdxt tests]# pwd
/root/tests
[root@licchen-test-dev001-bjdxt tests]# cp test_set_uid /projects/
[root@licchen-test-dev001-bjdxt tests]# ll /projects/test_set_uid
-rwxr-xr-x 1 root root 11258 Apr 27 22:13 /projects/test_set_uid
切换到另外一个普通账号执行程序:
[root@licchen-test-dev001-bjdxt ~]# su lic
[lic@licchen-test-dev001-bjdxt root]$ /projects/test_set_uid from_lic
[root@licchen-test-dev001-bjdxt ~]# cat /root/lic_test
from_root
发现文件内容没有变化,设置“设置用户ID”。
[root@licchen-test-dev001-bjdxt projects]# chmod u+s test_set_uid
[root@licchen-test-dev001-bjdxt projects]# ll test_set_uid
-rwsr-xr-x 1 root root 11258 Apr 27 22:13 test_set_uid
切换到普通账号执行程序:
[lic@licchen-test-dev001-bjdxt root]$ /projects/test_set_uid from_lic
root查看文件:
[root@licchen-test-dev001-bjdxt projects]# cat /root/lic_test
from_root
from_lic
发现文件已经更新。
之所以可以这样做,是因为文件的访问权限是有程序的有效用户ID决定的。
但是有一个函数是例外:access函数。该函数是按照进程的实际用户ID进行权限访问控制的。