- 论坛徽章:
- 0
|
在linux中每个进程有三个[实际上有第4个]用户标识符.
real uid : 真实用户ID.
saved uid : 已保存用户ID
effective uid : 有效用户ID
真实用户ID(real uid)是login时的用户.而在运行过程中,
用于所有的安全检查的是有效用户ID(effective uid).
一般情况下:
real uid = saved uid = effective uid
在某些场合下,使用用setuid,setruid函数可以改变effective uid,从而
使得程序运行时具有特殊的权限.常见的例子是linux系统中的passwd命令,
由于所有的用户信息包括用户密码都保存在/etc/passwd文件中,而/etc/passwd
文件只有root权限可以读写,若想让每个用户都只可以修改自己的密码,就必须
让普通用户暂时获得有限的读写/etc/passwd的权限.用setuid就可以解决这个
问题.
Linux setuid(uid)函数:
(1)如果由普通用户调用,将当前进程的有效ID设置为uid.
(2)如果由有效用户ID符为0的进程调用,则将真实,有效和已保存用户ID都设
置为uid.
Linux的setuid函数和Unix中的setuid函数的行为是不同的.
Unix中.setuid(uid)函数的行为:
(1)如果进程没有超级用户特权,且uid等于实际用户ID或已保存用户ID,则只
将有效的用户ID设置为uid.否则返回错误.
(2)如果进程是有超级用户特权,则将真实,有效和
已保存用户表示符都设置为uid.
这里主要的区别在于普通用户调用时的行为.产生这个问题的原因是POSIX和
BSD的实现差异,而linux却同时支持这两者.BSD中使用
setreuid(uid_t ruid, uid_t euid)
来设定真实用户ID(real uid)和有效用户ID(effective uid).这个函数在由有效
用户ID符为0的进程调用时,不会改变已保存用户ID.函数seteuid(uid_t uid)等价
于setreuid(-1,uid),只改变有效用户ID(effective uid).
例子:
使用setuid或是setruid,让非root用户也可以读取只有root用户有读写权限的
文件.
#假设此程序名为:setuid_ex
#要读取的文件为:root_only.txt 我修改改写了一个c语言版本:
view plain
copy to clipboard
print
?
/* * linux setuid example * */ #include #include #include void test_read_file(const char *name) { int fd = -1; fd = open(name, O_RDWR); if(fd { printf("=[ERROR]:read failed.\n"); } else { printf("=[OK]: read fuccessful\n"); close(fd); } } //打印uid和euid. void p_states(void) { int uid = 0; int euid = 0; printf("-----Current states--------------------------\n"); printf("real uid\t %d\n",getuid()); printf("effective uid\t %d\n",geteuid()); printf("---------------------------------------------\n"); } //调用setuid void run_setuid_fun(int uid) { if(setuid(uid) == -1) { printf("=[ERROR]:setuid(%d) error\n", uid); } p_states(); } //调用seteuid void run_seteuid_fun(int uid) { if(seteuid(uid)== -1) { printf("=[ERROR]:seteuid(%d) error\n", uid); } p_states(); } int main() { int t_re = 0; const char *file = "root_only.txt"; printf("\nTEST 1:\n"); p_states(); //此时real uid = login user id //effective uid = root //saved uid = root test_read_file(file); printf("\nTEST 2:seteuid(getuid())\n"); run_seteuid_fun(getuid()); //[2]此时 real uid= login user id // effective uid = login user id // saved uid = root test_read_file(file); printf("\nTEST 3:seteuid(0)\n"); run_seteuid_fun(0); //read uid = lonin user id //effective uid = root //saved uid = root test_read_file(file); printf("\nTEST 4:setuid(0)\n"); run_setuid_fun(0); //real uid = root //effective uid = root //saved uid= root test_read_file(file); printf("\nTEST 5 setuid(503)\n"); run_setuid_fun(503); //real uid = login user id //effective id = login user id //saved uid = login user id test_read_file(file); printf("\nTEST 6:seruid(0)\n"); //read uid = login user id //effective uid = login user id //saved uid = login user id run_setuid_fun(0); test_read_file(file); return 0; } makefile 需要在root权限下编译,在用户权限进行执行。
view plain
copy to clipboard
print
?
src=setuid_ex.c exe=setuid_ex cc=gcc flags=-g all: ${cc} ${flags} $(src) -o ${exe} chown root:root ${exe} ### 实际上chmod 4111改变了effective id 和saved uid的值. ### 这也是setuid setruid函数在不同权限间正常切换的前提. chmod 4111 ${exe}
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/72255/showart_2161592.html |
|