一、安全上下文
在操作系统中,用户执行某个指令,该指令会调用一系列的进程来完成操作,而当一个进程去访问某个文件时,会判断以下两点:
1.进程的运行者是谁
比如用户openstack执行/bin/cat命令来查看/etc/fstab,该程序(cat)就发起了一个进程。
[root@localhost tutor]# ls -l `which cat`
-rwxr-xr-x. 1root root 45224 Nov 22 2013 /bin/cat
由于cat的属组和属主都是root,如果cat命令发起的进程属于root用户,那么就意味着这些进程可以访问所有root组能访问的文件,而这是不允许的,故cat命令所发起的进程代表的是openstack用户及openstack用户所属的基本组。
2. 进程访问的对象
当openstack用户执行cat命令去访问/etc/fstab时,文件/etc/fstab本身也有属组和属主,而openstack用户能否访问该文件,取决于openstack用户是否具有对该文件的访问权限。
[root@localhost tutor]# ls -l /etc/fstab
-rw-r--r--. 1root root 932 Jul 11 14:15 /etc/fstab
文件/etc/fstab的属组和属主都是root,而openstack不属于root组,故openstack用户只能用other组的权限去访问该文件,而other组对此文件有读权限,故openstack用户通过cat命令发起的进程可以访问此文件。
通过判断以上两点,来确定某一个用户是否可以访问某个文件,即为安全上下文。
二、特殊权限
A. 设置属主的特殊权限(suid)
现在考虑这种情况,用户openstack无法访问文件/etc/shadow(该文件存放密码信息,只有管理员有权限访问),但openstack用户可以执行passwd命令来修改密码,而passwd命令代表openstack用户发起了一个进程,将用户修改后的密码保存到/etc/shadow文件中,这样一来似乎openstack用户又具备了访问/etc/shadow权限了,明显于安全上下文的判断相冲突,这是什么原因呢?我们需要引入特殊权限的概念:
[root@localhost tutor]# ls -l `which passwd`
-rwsr-xr-x. 1 root root 30768 Feb22 2012 /usr/bin/passwd
这里可以看到passwd命令有一个s权限,s表示的是suid,即set uid。当属主具有s权限时,意味着其他任何用户在执行此程序时,其进程的属主不再是发起者本人,而是这个程序的属主。故当openstack用户执行passwd命令时,passwd所发起的进程就属于passwd这个文件的属主,即root用户,而root用户是可以访问/etc/shadow文件的。
设置s权限的方式很简单:
chmod u+|-s /path/to/somfile
或者
chmod 4644 /path/to/somfile
有的文件s权限为小写,表示该文件的原有属主有执行权限,有的S则为大写,表示该文件没有执行权限。这里644前面还有一个4,其含义将在本文最后介绍。
B. 设置属组的特殊权限(sgid)
如果某文件的属组有s(sgid,表示set gid)权限,意味着执行此程序时,其进程的属组不再是运行者本人所属的基本组,而是进程文件的属组。
设置属组的s权限方式和设置属主的s权限一样:
chmod g+|-s /path/to/somfile
设置属组s权限的主要作用,和设置属主s权限不同,它不是为了让某个进程具有访问权限,而是将目录的属组属主,和目录中文件的属组属主分离开。看下面的例子:
[root@localhost tutor]# useradd hadoop
[root@localhost tutor]# useradd hive
[root@localhost tutor]# groupadd mygrp
# 创建两个用户hadoop、hive,创建组mygrp
[root@localhost tutor]# usermod -a -G mygrp hadoop
[root@localhost tutor]# usermod -a -G mygrp hive
# 为用户hadoop和hive添加额外组mygrp
[root@localhost tutor]# mkdir test
[root@localhost tutor]# ls -ld test
drwxr-xr-x. 2root root 4096 Jul 13 19:49 test
[root@localhost tutor]# chmod g+w test
# 新建目录test,并为test目录添加写权限
[root@localhost tutor]# ls -ld test
drwxrwxr-x. 2root root 4096 Jul 13 19:49 test
[root@localhost tutor]# chown :mygrp test
# 将test目录的属组改为mygrp
[root@localhost tutor]# ls -ld test
drwxrwxr-x. 2root mygrp 4096 Jul 13 19:49 test
[root@localhost tutor]# su hadoop
[hadoop@localhost tutor]$ cd test
[hadoop@localhost test]$ touch a.hadoop
# 切换到hadoop用户,在test目录下成功创建文件a.hadoop
[hadoop@localhost test]$ ls -l
total 0 -rw-rw-r--. 1hadoop hadoop 0 Jul 13 19:52 a.hadoop
[hadoop@localhost test]$ exit
exit
[root@localhost tutor]# su hive
[hive@localhost tutor]$ cd test
[hive@localhost test]$ touch a.hive
# 再切换到hive用户,成功创建文件a.hive
[hive@localhost test]$ ls -l
total 0 -rw-rw-r--. 1hadoop hadoop 0 Jul 13 19:52 a.hadoop -rw-rw-r--. 1hive hive 0 Jul 13 19:53 a.hive # 可以看到hadoop和hive这两个用户创建的文件和目录本身没有任何关系
[hive@localhost test]$ whoami
hive
[hive@localhost test]$ echo hello >> a.hadoop
bash:a.hadoop: Permission denied # 当前用户为hive,不能编辑hadoop创建的文件。
如果想让用户hive访问a.hadoop,则需要修改hadoop的属主或属组,如果有大量类似的文件都需要修改,则会造成很大的不便,sgid的作用就在这里体现出来了。
[root@localhost tutor]# ls test -ld
drwxrwxr-x. 2root mygrp 4096 Jul 13 19:53 test
[root@localhost tutor]# chmod g+s test
# 为test目录的属组添加s属性
[root@localhost tutor]# ls test -ld
drwxrwsr-x. 2 root mygrp 4096 Jul 13 19:53 test
[root@localhost tutor]# cd test
[root@localhost test]# su hadoop
[hadoop@localhost test]$ touch b.hadoop
# 切换为hadoop用户,然后再创建一个文件
[hadoop@localhost test]$ ls -ld
drwxrwsr-x. 2root mygrp 4096 Jul 13 20:25 . # 当前目录的属组为mygrp
[hadoop@localhost test]$ ll
total 0 -rw-rw-r--. 1hadoop hadoop 0 Jul 13 19:52 a.hadoop -rw-rw-r--. 1hive hive 0 Jul 13 19:53 a.hive -rw-rw-r--. 1hadoop mygrp 0 Jul 13 20:25 b.hadoop # 此时会发现刚才由hadoop用户创建的文件b.hadoop其属组不再是其基本组了,而变成了mygrp
[hadoop@localhost test]$ exit
exit
[root@localhost test]# su hive
[hive@localhost test]$ echo hello >> b.hadoop
[hive@localhost test]$ cat b.hadoop
Hello # 用户hive可以编辑hadoop创建的b.hadoop文件了
[hive@localhost test]$ rm b.hadoop
# 用户hive甚至可以删除b.hadoop
设置s权限是个比较危险的操作,试想root用户写了一个脚本,其中含有 rm -rf / 这样的操作,然后为该脚本设置了s权限,那么意味着任何用户都可以执行操作系统自杀命令。故不到万不得已的情况,不要随意设置s权限。
三、粘贴位权限(冒险位权限:sticky)
上面的例子中当某个目录的属组有了s权限后,以该属组为附加组的用户,可以随意操作该目录中其他用户创建的文件,这样是很不合适的,于是就引出了另外一个权限:t权限,意为sticky,粘贴位权限。
t权限是附加在other上的权限,表示该权限附加在文件的属主上,即在某个公共目录内,每个用户只能删除自己创建的文件,即使其他用户有写权限,也不能删除该文件。该权限同样也有大小写之分:
小写t:表示原来有执行权限
大写T:表示原来没有执行权限
更改t权限的方法也和s权限一样,格式如下:
chmod o+|-t /path/to/somefile
下面来演示一下t权限的使用:
[root@localhost test]# cd ../
[root@localhost tutor]# chmod o+t test
# 使用root用户为test目录增加t权限
[root@localhost tutor]# ls -ld test
drwxrwsr-t. 2root mygrp 4096 Jul 13 20:47 test
# 可以看到具有t权限的目录变为蓝底了
[root@localhost tutor]# su hadoop
[hadoop@localhost tutor]$ cd test
[hadoop@localhost test]$ touch c.hadoop
# 现在切换回hadoop用户,然后创建c.hadoop文件
[hadoop@localhost test]$ exit
exit
[root@localhost tutor]# su hive
[hive@localhost tutor]$ cd test
[hive@localhost test]$ ll
total 0 -rw-rw-r--. 1hadoop hadoop 0 Jul 13 19:52 a.hadoop -rw-rw-r--. 1hive hive 0 Jul 13 19:53 a.hive -rw-rw-r--. 1hadoop mygrp 0 Jul 13 20:47 b.hadoop -rw-rw-r--. 1hadoop mygrp 0 Jul 13 20:51 c.hadoop
[hive@localhost test]$ echo hello >> c.hadoop
[hive@localhost test]$ cat c.hadoop
Hello # 再切换到hive用户,可以编辑由hadoop创建的c.hadoop文件
[hive@localhost test]$ rm c.hadoop
rm: cannotremove `c.hadoop': Operation not permitted # 但是hive用户无法创建其他用户创建的文件
下面总结一下特殊权限和粘贴权限和属主属组的对应关系:
u位:s权限
g位:s权限
o位:t权限
上述三位对应的sst权限也可以组成一个8进制的数字:
000(0)
001(1)
010(2)
100(4)
011(3)
101(5)
110(6)
111(7)
在为文件修改权限时,这个代表sst权限的8进制数放在普通权限的前面,故修改某个文件的权限如果写成如下形式:
chmod 6664/path/to/somefile
它就表示该文件的属主、属组都有s权限、读写权限,其他用户只有读权限。由于sst都属于特殊权限,所以将这三者集中管理,而不是和ugo的普通权限一起管理。
下面来举个例子演示一下通过8进制数来修改文件特殊权限的过程:
[root@localhost tutor]# cp /etc/fstab test
[root@localhost tutor]# cd test
[root@localhost test]# ll
-rw-rw-r--. 1hadoop mygrp 6 Jul 13 20:54 c.hadoop -rw-r--r--. 1root mygrp 932 Jul 13 21:14 fstab
[root@localhost test]# chmod 6640 fstab
[root@localhost test]# ll
-rw-rw-r--. 1hadoop mygrp 6 Jul 13 20:54 c.hadoop
-rwSr-S---. 1 root mygrp 932 Jul 13 21:14 fstab
注意,sst权限的设置只能通过手动完成,不要通过umask的方式来操作。