从getuid()&+geteuid()谈文件特殊权限

本文多处参考以下文章,向作者致谢。勉为其难算作原创~~~

http://www.groad.net/bbs/read.php?tid-868.html

http://www.groad.net/bbs/read.php?tid=749
http://www.groad.net/bbs/read.php?tid=367

函数原型:
#include <unistd.h>
#include <sys/types.h>

uid_t getuid(void);
uid_t geteuid(void);

说明:
getuid() 获取进程的实际用户ID,geteuid() 获取进程的有效用户ID.

有效用户ID(EUID)表示该ID是程序的所有者,一般为程序的实际执行者。
真实用户ID(UID) 最初运行该程序的用户ID。
当程序未设置SUID的时候,两者是相同的,但是当程序设置了SUID时,两者可能不同。

测试程序:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>

int main()
{
    int fd;
    printf("uid = %d, euid = %d ", getuid(), geteuid());
    
    if( (fd = open("test.txt", O_RDWR)) == -1 ) {
        printf("Open failure, errno is %d :%s \n", errno,strerror(errno));
        exit(1);
    } else {
        printf("Open successfully!\n");
    }
    while(1) {}
    close(fd);
    return 0;
}

测试步骤及结果:

1.
a. root下编译链接程序并执行。程序运行成功:
uid = 0,euid = 0 
Open successfully!
b. 查看程序运行情况(ps -ef|grep a.out):
root     15116 14726 99 19:09 pts/8    00:00:25 ./a

2.
a. root下编译链接程序,修改目录权限,并在test用户下运行程序。返回错误,test.txt文件(由root建立)拒绝访问。修改test.txt权限,程序运行成功:
uid = 1001, euid = 1001 
Open successfully!
b. 查看程序运行情况:
test     15185 14832 99 19:17 pts/9    00:01:35 ./a.out

3. 
a. root下修改程序权限:
chmod u+s a.out (或者 chmod 4776 a.out)
b. 在test用户下运行程序,由于2.a步中已经合理调节权限,程序运行成功:
uid = 1001,euid = 0
Open successfully!
c. 查看程序运行情况:
root     15193 14832 99 19:26 pts/9    00:00:05 ./a.out

4. 
a. test用户下重新建立test.c,编译链接为a.out   
b. 修改权限:chmod u+s a.out
c. root用户下执行程序。运行成功:
uid = 0, euid = 1001
Open successfully!
d. 查看程序运行情况:
test     15226 14726 99 19:32 pts/8    00:00:10 ./a.out

通过以上四组例子,尤其是第三组和第四组,可以比较出UID 和EUID 的区别。当程序设置了SUID时,UID通常为最初执行程序的用户ID,而EUID通常为程序的所有者,也是程序的实际执行者。如在测试3中,a.out为root所有,最初执行者为1001用户,程序的实际执行者为root.

实际上,chmod u+s a.out的命令,就是为a.out设置SUID的过程。SUID是文件的特殊权限之一。这个权限位置位了,当其他用户运行这个程序时,都会拥有这个程序的拥有者的权限。如passwd命令
root@linux# ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 37100 Sep  3  2010 /usr/bin/passwd
user权限的x位上为s,便是passwd的SUID被置位的标记。此时,一般用户之所以可以通过passwd来修改自己的密码,便是因为passwd的SUID被置位,此时,一般用户执行passwd是,其实拥有passwd所有者的权限,也就是root的权限,或者理解为,实际上运行passwd程序的,就是root。程序运行情况如下:
root     15296 14832  0 20:10 pts/9    00:00:00 passwd
否则,一般用户是无法自己修改password的,因为,一般用户无权对/etc/shadow文件操作:
-rw-r----- 1 root shadow 1307 Sep 21 17:48 /etc/shadow

文件特殊权限

特殊权限又称为第四权限(fourth permission),包含suid sgid sticky。
suid    在 u 组的 x 位表示
sgid    在 g 组的 x 位表示
sticky  在 o 组的 x 位表示
在 r-xr-xr-x 这样的一组权限设定中,u 组中已经具备x权限,那么在设定suid权限时,用小写s表示,形如:rws。同样的在g组中也具备x权限,那么设定sgid时,也用小写s表示,此时g组的形式为r-s。在o组中,也已经具备x权限,那么在设定sticky时,用小写t去掉x表示,形如r-t。那么整个形式在设定后为:r-sr-sr-t。
在 r--r--r-- 这样的一组权限设定中,各个组的x位都没有相应的权限,那么在设定suid sgid sticky时,则x位都用相应的大写字母表现,设定后形式为:r-Sr-Sr-T。

使用chmod修改特殊权限
chmod u+s file
chmod g+s file
chmod o+t file
特殊权限的数字表示:
suid---4  sgid---2  sticky---1
chmod 2755 file
chmod 7755 file

特殊权限的作用
suid 权限可以让执行这个文件时,是以文件的拥有者的权限进行,而不是执行这个命令的用户本身的权限。
sgid和sticky可以设置在目录上:
那么在设置有sticky位的目录里的文件,只有文件的拥有者及root才可以删除文件权限,而不是看write的权限来决定。
假如一个目录有sgid的权限,那么只有拥有这个目录的组中的成员,才能在这个目录中创建文件。

a. suid:
ls -l /bin/ping
-rwsr-xr-x 1 root root 34716 2010-07-28 16:44 /bin/ping
从上面的指令的结果看出,ping 指令具有 suid 的特殊权限,那为什么这样呢?
ping 指令使用 ICMP 协议测试计算机与计算机之间是否连通。而在linux的kernel里面设定了只有 root 才有权限控制ICMP的封包。所以,设定ping命令具有suid特殊权限,且ping命令的所有者(owner)是root后,不管是哪一个使用者使用ping这个指令都是以root的身份来执行这个命令。
chmod u-s /bin/ping,重新以非root用户执行ping,可测试该权限位。

b. sticky:
测试过程:
构造目录及文件,服用相应权限,用其它用户进行删除测试
root@# mkdir t
root@# chmod 755 t
root@# chmod o+t t
root@# cd t
root@# touch t.txt
root@# chmod 777 t.txt
test@# cd t 
test@# ls -l
-rw-r--rw- 1 root root 0 2011-10-12 22:02 t
test@# rm t
rm: cannot remove `t': Operation not permitted
sticky标记的目录下的文件,只有root和文件的拥有者才能删除,忽略其它用的write权限。但是,其他用户是可以写文件的(只是不能删除)
test@# echo test > t

c.sgid
假如一个目录有sgid的权限,那么只有拥有这个目录的组中的成员,才能在这个目录中创建文件。Q???尚待研究
如果目录被设置为 setgid,那么在该目录下创建的文件都属于目录所属的同一个组。??

以下文字有利与理解EUID和EGID,及文件(进程)特殊权限的含义:


登录系统成功后,系统会给用户的shell一个身份,包括一个真实用户标识(UID),一个或多个真实用户组标识(GID),一个有效用户标识(EUID)和有效用户组标识(EGID)。开始时,EUID和EGID分别与UID和GID相同。这些ID号可以在文件/etc/passwd中找到,它们被系统用来标识用户和用户组。EUID 和 EGID决定了进程读、写或执行文件的权限。如果进程的EUID与文件属主的真实UID相同,则进程具有文件的属主访问权限。如果进程的EGID和真实的GID相同,则进程拥有属主的组特权。

EUID和EGID可以被改变为另一个属主的ID号。可以通过把EUID(或EGID)变成另一个属主而拥有其他用户的进程。(EUID/EGID编程)
阅读更多
个人分类: Linux
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭