网上关于uid这一块的东西多是多,只是大多都太乱了,今天偶然发现一个感觉很好的,mark一下~~~
1 名词解释
uid(user id) |
一个uid表示系统中的一个用户,可对应多个gid |
||||
gid(group id) |
一个gid表示系统中的一个组,可对应多个uid |
||||
ruid(real user id) |
一个进程的真实uid,如果不是root,进程间的signal必须是相同的ruid之间才能进行,例如子进程继承了父进程的ruid,所以可以互相signal。 |
||||
rgid(real group id) |
一个进程的真实gid |
||||
euid(effective user id) |
一个进程的有效uid,当一个进程创建或访问文件时,用的不是ruid的权限,而是euid的权限。 |
||||
egid(effective group id) |
一个进程的有效gid,原理同上 |
||||
suid(saved user id) |
一个特权进程(privilege process,它的euid是特权值)在运行中间可能需要做一些非特权工作,就会将euid设置为某个非特权的,这时会将特权值存放在suid,注意,这时进程已经变成非特权进程(unprivileged process)了,而一般普通的非特权进程是无法主动把自己变成一个特权进程的,因为对euid的赋值只能是ruid、euid、suid之一,但由于前面把特权值存放在了suid,所以这时进程就可以恢复成特权进程了。 |
||||
sgid(saved group id) |
原理同上,给一个特权进程恢复的机会。 |
||||
fsuid(file system user id) |
linux引入的,单独控制对文件系统的访问权限,不过一旦euid发生变化,fsuid立即跟着变化。fsuid的用途是,允许一些程序(例如NFS server)拥有一些已知uid的对文件系统的访问权限,但是不拥有uid对应的发送signal的权限。也就是说,在不修改ruid、euid的情况下,就改变了文件系统访问权限。对fsuid的赋值只能是ruid、euid、suid之一。 |
||||
fsgid(file system group id) |
原理同上,赋值只能是rgid、egid、sgid之一。 |
文件 |
文件夹 |
|
读r |
读文件 |
列出文件夹内容。屏蔽这个位可以对别人隐藏文件夹中各个文件名。 |
写w |
写文件 |
创建或移除文件。屏蔽这个位可以使文件夹中的文件数目不变。 |
执行x |
执行文件(run it as a program) |
访问文件夹中的文件。如果不具有x权限:无法cd到这个文件夹;无法创建或删除文件(即使有文件夹w权限);无法读取或写入文件内容(即使对文件夹和文件本身都有rw权限)。 屏蔽这个位,用户唯一能做的就是查看文件夹有哪些文件。 |
结论是:必需对文件夹同时拥有wx权限,才能创建或删除文件;必需对文件夹拥有x权限并对文件拥有r或w权限,才能读或写文件。
2.3 还有三种特殊权限(影响可执行文件,有些系统还影响文件夹)
文件 |
文件夹 |
|
SUID(setuid bit) |
如果设置,当文件执行时设置进程的euid,这个值是文件拥有者的uid |
|
SGID(setgid bit) |
如果设置,当文件执行时设置进程的egid,这个值是文件所属的组ID |
某些系统中,如果对某文件夹设置了这个位,那么无论是拥有者属于哪个组,在此文件夹中创建的文件和此文件夹同组。 |
sticky bit |
如果设置,执行文件时,即使程序结束,二进制映像也保存在swap分区,可以实现快速重启。但是linux并不支持这个特点。 |
对文件夹设置这个位,则只有此文件夹的拥有者,或者文件夹中文件的拥有者,或者超级用户才能重命名或删除文件。 Solaris有一个独有特性,针对不可执行文件,如果设置了这个位,不会在内核中缓冲。 |
2.4 某些文件系统相关属性
例如访问控制列表(ACLs,表示一个文件系统只能由哪些用户访问),一个文件能否被压缩、修改或核心转储,这些属性通常是通过文件系统特有的命令来设置的(例如ext2可以用chattr,FFS可以用chrflags)。
所以尽管文件本身的属性可能允许用户进行操作,但是实际操作还是会失败,例如:文件系统属性不允许,文件系统挂载为只读的。
2.5 一个文件创建的时候就会分配拥有者和组,通常来说,拥有者是当前用户,组是文件所属文件夹的组。不过这也不是绝对的,取决于操作系统和文件系统的不同。可以用chown和chgrp修改文件的拥有者和组。
3 文件权限修改(shell命令)
3.1 相关命令
添加、删除、修改用户或组(这些命令影响uid和gid):useradd/userdel/usermod/groupadd/groupdel/groupmod
修改文件拥有者:chown
修改文件所属组:chgrp
修改文件属性:chmod
设置忽略掩码:umask
3.2 chmod命令
下面详细说明一下chmod,首先我们看一下Linux中对文件权限的显示
-
---------- 1 guanxin root 0 12-28 09:35 empty.txt -rwx------ 1 guanxin root 0 12-28 09:36 owner.txt ----rwx--- 1 guanxin root 0 12-28 09:36 group.txt -------rwx 1 guanxin root 0 12-28 09:36 others.txt
可以看到一共有10个位置,第一个位置标示文件类型(–普通文件,d文件夹,b块设备文件,c字符设备文件,l链接文件,p命名管道文件,s套接字文件),接下来的9个位置分别是拥有者、文件所属组的组用户、其它用户的读、写、执行权限(如果不具有权限显示–,具有权限显示一个对应字母)。
在Unix-like系统中,文件夹也是文件的一种,所以对于文件夹也可以设置权限。例如:
-
drwxrwxr-- 2 root root 4096 12-28 09:36 test
以这个test文件夹为例,u和g用户拥有全部权限,但是o用户只能ls test,因为具有r权限,但是不能cd test(这需要x权限),也不能rm -ftest/others.txt(这需要wx权限,注意!!!创建和删除文件只需要拥有文件夹的wx权限,而无需对文件本身具有任何权限,例如上面的empty.txt文件的权限是全空,但是用户只要拥有对test文件夹的wx权限,仍然可以删除它!!!)。
下面列举几个常用命令:
-
chmod g+rwx test # 给g用户添加rwx三种权限 chmod o-wx test # 删除o用户的wx权限 chmod +x haha.sh # 给脚本haha.sh添加执行权限,前面没有指定用户,则默认是a,全部。
设置SUID位
-
chmod u+s a.out -rwsr-xr-x 1 guanxin root 7577 12-26 12:31 a.out
可以看到owner对应的x权限变成了小写s,如上所述,设置SUID位就会使运行这个文件时获得guanxin用户的权限。当然执行完,权限也就消失了。
一般这功能用于临时获取root权限,例如执行/usr/bin/passwd修改密码,需要访问修改/etc/passswd文件,而这个文件对其它用户而言是只读的,那我想修改自己的密码怎么办?答案是设置SUID位。
-rwsr-xr-x1 root root 27768 2007-01-07 /usr/bin/passwd
可以看到这个文件的拥有者是root,所以执行时会获得root权限。
对于文件夹设置SUID位是没有任何作用的,对于没有x权限的文件设置SUID位,结果是一个大写S标志。
-
-rwS------ 1 guanxin root 15 12-28 10:57 owner.txt echo haha >>owner.txt # 如果对owner.txt进行修改,那么它会自动丢失大S属性。 -rw------- 1 guanxin root 20 12-28 11:26 owner.txt
鉴于SUID位容易有安全隐患,万一有人无意中设置被别人钻空子(使得运行特权进程后,不正常结束,通过缓冲区溢出或代码注入继续运行特权程序),所以许多操作系统会忽略对脚本的SUID设置。
设置SGID位
-
chmod g+s a.out -rwsr-sr-x 1 guanxin root 7577 12-26 12:31 a.out
这时g用户对应的x位变成了小s,它表示文件启动执行时,会获得root组的组权限(设置egid)。同样也是如果对不带x权限的文件设置,会显示大写S。
如果对文件夹设置SGID位,表示在此文件夹中创建的文件,组都是和文件夹相同。
-
drwxrwxrwx 2 root root 4096 12-28 11:43 test # 没对test文件夹设置SGID位 -rw-rw-r-- 1 guanxin2 guanxin2 0 12-28 11:43 haha3.txt # 用户guanxin2创建的文件是创建者的名字和组 chmod g+s test drwxrwsrwx 2 root root 4096 12-28 11:43 test # 对test文件夹设置SGID位 -rw-rw-r-- 1 guanxin2 root 0 12-28 11:45 haha4.txt # 用户guanxin2创建的文件拥有者还是guanxin2,但是组变成了root
设置sticky bit
-
chmod +t a.out
C函数可以用chmod/fchmod来修改文件属性。下面两个表格是在进程运行中如何修改uid和gid从而获得不同的权限(空白表示值不变)。
before call |
ruid |
euid |
suid |
fsuid |
|
setuid( e ) |
euid != 0 (e是ruid、euid、suid之一) |
e |
e |
||
euid == 0(注意,这种情况下,进程无法回到特权级,因为suid也变了。) |
e |
e |
e |
e |
|
seteuid( e ) |
euid != 0 (e是ruid、euid、suid之一) |
e |
e |
||
euid == 0 |
e |
e |
|||
setreuid( r, e ) |
euid != 0 (r是ruid、euid之一,e是ruid、euid、suid之一) |
r |
e |
e |
e |
euid == 0 |
r |
e |
e |
e |
|
setresuid( r, e, s ) |
euid != 0 (r,e, s是ruid、euid、suid之一) |
r |
e |
s |
e |
euid == 0 |
r |
e |
s |
e |
|
setfsuid( f ) |
euid != 0 (f是ruid、euid、suid、fsuid之一) |
f |
|||
euid == 0 |
f |
before call |
rgid |
egid |
sgid |
fsgid |
|
setgid( e ) |
euid != 0 (e是rgid、egid、sgid之一) |
e |
e |
||
euid == 0 |
e |
e |
e |
e |
|
setegid( e ) |
euid != 0 (e是rgid、egid、sgid之一) |
e |
e |
||
euid == 0 |
e |
e |
|||
setregid( r, e ) |
euid != 0 (r是rgid、egid之一,e是rgid、egid、sgid之一) |
r |
e |
e |
e |
euid == 0 |
r |
e |
e |
e |
|
setresgid( r, e, s ) |
euid != 0 (r,e, s是rgid、egid、sgid之一) |
r |
e |
s |
e |
euid == 0 |
r |
e |
s |
e |
|
setfsgid( f ) |
euid != 0 (f是rgid、egid、sgid、fsgid之一) |
f |
|||
euid == 0 |
f |
参考文档
http://en.wikipedia.org/wiki/Sticky_bit
http://en.wikipedia.org/wiki/User_id
http://en.wikipedia.org/wiki/File_system_permissions
GNUcoreutils.info
http://blog.sina.com.cn/s/blog_4c23939b0100q4zl.html
http://www.2cto.com/os/201208/147429.html
http://en.wikipedia.org/wiki/Sgid