关于目录的可执行权限

  • 什么叫做“进入工作目录”
  • 目录的可执行权限
  • 参考资料


什么叫做“进入工作目录”

普通文件里面保存了实际数据,目录保存了文件之间的层次关系,二者都是对磁盘的一种抽象。文件一定要有,它指明了一段数据的起始和结束;目录则是可有可无,把所有文件放到同一个地方(扁平化结构)也未尝不可,尽管有些混乱。
工作中最常用的两个命令是 lscdcdchange directory 的缩写,当我们 cd 到一个目录的时候,我们(操作系统)从磁盘上得到了哪些信息?到底是切换目录失败导致得不到想要的信息还是因为得不到想要的信息导致切换目录执行失败?
当我们把一个目录设为当前工作目录时,我们能够从这个目录所属的数据块(data block)中获取到其子目录/子文件的 inode 信息。目录的作用就是就其子文件(包含目录)做一个封装,以一个统一的名字出现在上一级目录下,以此类推,直到一个唯一的根目录。也就是说,我们如果无法从一个目录里面找到真正保存数据的文件,那么这个目录的存在就是没有意义的。当系统所有用户都不能切换到这个目录时,这个目录就是死胡同,就是垃圾,可以直接被删除。在无法得到一个目录的子文件信息的情况下,系统自然不能把工作目录切换到这个目录。

目录的可执行权限

目录里到底存放了什么东西?它存放的是目录下面的文件名(包括目录名)和 inode 的对应关系。我没有找到查看目录内容的命令,不过我找到一个查看 gittree object 内容的命令。Tree object 就相当于文件系统里的目录,用来保存对象(object)之间的结构关系,一个 tree object 可以包含任意数目的 blob object 和任意数目的 tree object,就像一个目录包含子目录和文件。

[root@host4 2a]# git cat-file -p aa0a6bfac125c267c340217b4af6452da05d22f8
100644 blob 77697657acc98a46dc0daee61f0fd36512890df5	.gitignore
100644 blob 17792500738a2715c431bccd0912fd48ce1f194a	README.md
100644 blob 21a06864a559a958fe6f6e9bf1afb20c7341770f	basis.py
100644 blob 74ebe500941dde6ca456a699233aa5471642c20b	conditions.py
100644 blob 584cb4df0bedecc0b825be038e7735c7f5c82dc5	demo.txt
100644 blob d077cac4c3d1b5f6b8fc5ba7c2eda28853ade6b3	dicts.py
100644 blob 0d4826635f25147073ca3adad30fec0b51df3248	ex1.py
100644 blob 777bf74e271485132aeefac679cbf853ab277fc4	ex10.py
100644 blob dec1d309f8d123593a4cd71ad49ba2866d1e2780	ex11.py

下面我先说一下我的观点:

  • 目录的写权限表示可以修改目录的 data block,即在目录里新建文件(包括目录)、删除文件、重命名文件(可以看作删除旧文件,建立新文件的组合),这一点毋庸置疑。
  • 目录的读权限表示可以读取目录的 data block 里的 文件名,但是无法得到文件名对应的 inode 部分,这样在使用 ls -l 选项时没有 inode 信息,程序自然会报错。
  • 目录的执行权限代表可以获取 文件名-> inode 之间的对应关系。这时如果没有读权限将不能看到文件名列表,但这并不妨碍目录功能的正常发挥,你给出一个文件名(没有提示,没有自动补全),我就能找到对应的 node 数据。就像银行本票一样,银行不会告诉你我们在什么时候和什么人签了一个本票(目录不会给用户显示任何文件名信息),但是只要你拿出真的本票(银行真正签过的,类比于给出目录里确实存在的文件名),你就能取出现金(得到文件名对应的 inode 编号)。

下面是验证过程。
当用户只对目录有读权限时,可以正常从目录的数据块里得到文件名信息,但是由于缺少执行权限,无法获取文件名的 inode,文件的属性信息又保存在文件的 inode 里面,所以执行 ls -l 会报错。这里 ls 没有带 -l 选项也会报错,说明 ls 即便单独执行也需要查看文件的 inode 信息,只是不显示出来而已。

[gy@localhost tmp]$ ll -d ssh/
drwxr-xr--. 2 root root 225 Mar 10 14:39 ssh/
[gy@localhost tmp]$ ls ssh/
ls: cannot access ssh/moduli: Permission denied
ls: cannot access ssh/sshd_config: Permission denied
ls: cannot access ssh/ssh_config: Permission denied
ls: cannot access ssh/ssh_host_rsa_key: Permission denied
ls: cannot access ssh/ssh_host_rsa_key.pub: Permission denied
ls: cannot access ssh/ssh_host_ecdsa_key: Permission denied
ls: cannot access ssh/ssh_host_ecdsa_key.pub: Permission denied
ls: cannot access ssh/ssh_host_ed25519_key: Permission denied
ls: cannot access ssh/ssh_host_ed25519_key.pub: Permission denied
moduli      sshd_config         ssh_host_ecdsa_key.pub  ssh_host_ed25519_key.pub  ssh_host_rsa_key.pub
ssh_config  ssh_host_ecdsa_key  ssh_host_ed25519_key    ssh_host_rsa_key

当用户只对目录有执行权限的时候,bash 的自动补全功能失效(即目录下文件名的自动补全是在用户拥有目录的执行权限的前提下进行的),ls 命令也无法给出文件名列表,但是我们只要提供正确的文件名,还是能够获得真正的数据,这有点像摸黑找东西,全凭平时对目录结构的了解。这样的设置能够阻止陌生人的非法访问(他不知道目录里面到底有哪些文件)。

[gy@localhost tmp]$ ll -d ssh/
drwxr-x--x. 2 root root 225 Mar 10 14:39 ssh/
[gy@localhost tmp]$ ls -l ssh
ls: cannot open directory ssh: Permission denied
[gy@localhost tmp]$ ls ssh
ls: cannot open directory ssh: Permission denied
[gy@localhost tmp]$ ls -l ssh/sshd_config
-rw-------. 1 root root 3907 Mar 10 14:39 ssh/sshd_config
[gy@localhost tmp]$ ls -l ssh/abc
ls: cannot access ssh/abc: No such file or directory

参考资料

鸟哥的 Linux 私房菜第五章:Linux 的文件权限与目录配置