root
我可以使用以下权限将 /etc/passwd 文件复制到我的主目录:
-rw-r--r--. 1 root root 2751 Dec 24 21:26 /etc/passwd
我不能做同样的事情:
-rw-------. 1 root root 43591 Dec 27 18:32 /var/log/messages
所以我猜测 的读取权限others
使得复制成为可能?
为了创建硬链接,我在主目录中以 root 用户身份创建了 file1,并尝试以普通用户身份创建硬链接。我没能做到。
-rw-r--r--. 1 root root 0 Dec 27 18:39 file1
是什么阻止了硬链接的创建?
file1所在目录权限为:
drwx------. 18 student student 4096 Dec 27 18:42 .
我能够将 file1 重命名为 file2 所以我猜测,与复制相同,读取权限others
正在使这种情况发生?
最后,我无法将 file2 移动到其他位置。为什么?
编辑:我看过一个解释硬链接权限的问题,但我不明白复制、移动和重命名其他用户的文件和目录需要什么权限。
答案1
基本隐喻:目录不是文件夹
要理解的基本概念是目录。这很重要:Unix 确实如此不是有文件夹,它有目录。
这个区别很重要:文件夹包含事物。一个目录列表事物。如果您想到文件夹,您的脑海中就会出现错误的比喻。想想您在办公楼大厅找到的公司目录:该目录没有包含办公室,它列表他们。同样,您的电话簿也不会包含你的朋友,它列表他们。另一方面,(物理)文件夹实际上确实包含它保存的(物理)文件。
文件序列号
在 Unix 中,文件没有名称。文件只有一个文件序列号 (FSN)。 FSN 在单个文件系统中是唯一的:同一文件系统上没有两个文件具有相同的 FSN,并且单个文件在其生命周期内仅具有单个 FSN。但请注意,文件位于不同的文件系统可以具有相同的 FSN。
索引节点
注意:您可能会遇到这个术语索引节点。它本质上意味着同样的事情。文件序列号是为了 Unix 标准化而发明的名称,因为索引节点实际上是某些文件系统的实现细节,许多现代文件系统甚至没有有inode 不再存在……但它们仍然需要 FSN。此外,许多现代的 Unices 允许挂载外部文件系统,这些文件系统显然也没有 inode,因为这纯粹是 Unix 的事情(例如,在 Linux 中挂载 FAT、exFAT 或 NTFS 文件系统)。不过,这些外部文件系统的 Unix 驱动程序仍然需要合成 FSN,因为许多文件系统 API 都是基于 FSN 的。
目录
目录是特殊文件那个同事名字到FSN。在非常早期、非常简单的 Unix 文件系统中,目录实际上只是一个文件(类似于文本文件),看起来像
12345 foo
54321 hello.txt
34343 My 2021 taxes.xlsx
当然,现代文件系统要复杂得多,但是从概念上来说,即使在最复杂的文件系统中,这仍然是今天的工作方式。
三个基本概念
如果您了解这三个概念,您就了解了有关 Unix 文件系统和 Unix 权限所需了解的一切:
- 文件没有名称,只有文件序列号。
- 目录是文件。
- 目录将名称与 FSN 相关联。
想想我们的电话系统是如何工作的:我们只有号码,但我们有目录(电话簿、黄页,或者更现代的是我们手机上的联系人应用程序)将姓名与这些号码相关联。
(硬)链接
之间的关联姓名和FSN被称为关联或有时硬链接(在可能与符号链接/软链接混淆的情况下)。
三个基本概念的后果
一旦你内化了这三个概念,其他一切都应该水到渠成。
现在应该很明显,没有什么可以阻止您在不同目录中甚至在同一目录中为同一 FSN 创建多个名称→FSN 链接。换句话说,同一个文件可以有多个名称并存在于多个路径中。
很明显,这会导致分层目录结构:因为目录只是像任何其他文件一样的文件,所以它们像任何其他文件一样具有 FSN,因此,我可以在目录中列出目录。
虽然不太明显,但了解该rm
实用程序确实很重要不是实际上删除一个文件!它删除了一个关联,换句话说,它删除目录中的一个条目。所使用的库函数和内核系统调用rm
实际上是被调用的unlink
。事实上,你不能实际上在 Unix 中删除文件。如果没有指向文件的链接(换句话说,如果文件有 0 个名称)并且文件没有打开的文件句柄,文件将被自动删除。
这也解释了许多 Windows 用户感到困惑的事情:我怎么可能删除在某些应用程序中仍然打开的文件?该应用程序如何不崩溃?嗯,根据我们在上一段中学到的知识,答案很简单:他们没有删除文件,他们只删除了姓名。该文件仍然存在。它仍然可以有其他名称,但即使这是姓氏,该文件也不会被删除,直到应用程序关闭它。事实上,创建一个临时文件,打开它,然后立即再次“删除”它,是需要临时存储数据但又不想用临时文件弄乱文件系统的 Unix 应用程序的常见设计模式。
将概念应用于权限
如果您了解目录是文件,并且目录将名称与数字相关联,那么权限就会变得清晰:
- 如果你想改名, 你需要写目录的新名称并删除(这也是一种形式写作)旧的,因此你需要
w
仪式许可到目录, 但无法访问该文件。事实上,重命名实际上与文件本身没有任何关系,它只涉及姓名这是不是文件本身的属性。 - 如果你想列出一个目录,你需要读它的内容,因此需要
r
对该目录的读取权限。 - 创建硬链接只是写作到目录,因此您需要
w
对该目录的写入权限。等等。
具体例子
考虑到我们的三个核心概念,我们应该能够回答您的所有问题:
复制
我可以使用以下权限
/etc/passwd
将拥有的文件复制到我的主目录:root
-rw-r--r--. 1 root root 2751 Dec 24 21:26 /etc/passwd
我不能做同样的事情:
-rw-------. 1 root root 43591 Dec 27 18:32 /var/log/messages
所以我猜测 的读取权限
others
使得复制成为可能?
那是对的。想想“复制文件”实际上是什么意思是: 你是创造A新的文件(这自动也意味着您需要给它一个名称,即创建一个关联目标目录中的条目),其中包含相同内容作为原始文件。
为此,您需要两个权限:
- 您需要
w
目标目录的 rite 权限才能创建指向新创建文件的硬链接。 - 您需要
r
原始文件的 ead 权限才能读取其内容,因为如果您无法读取其内容,那么如何重新创建它?
关联
为了创建硬链接,我
file1
在主目录中创建了 root 用户,并尝试以普通用户身份创建硬链接。我没能做到。-rw-r--r--. 1 root root 0 Dec 27 18:39 file1
标准 Unix 权限模型中没有任何内容可以阻止您创建硬链接。您所需要的只是w
对该目录的 rite 权限。该文件的权限是无关紧要的,因为您不需要触及它。
我刚刚在我的操作系统(macOS 12.1“Monterey”)的 APFS 文件系统上测试了它,它运行得很好。
fs.protected_hardlinks
是什么阻止了硬链接的创建?
Unix 权限系统中没有任何内容。但是,由于您使用的是 Linux,因此有一个特定于 Linux 的配置选项可能会阻止您这样做:sysctl fs.protected_hardlinks
。
引用自官方 sysctl 文档[大胆的强调我的]:
受保护的硬链接
[…]
当设置为“
0
”时,硬链接创建行为不受限制。当设置为“
1
”时如果用户尚不拥有源文件,或者没有对该源文件的读/写访问权限,则无法创建硬链接。
看起来您已将其配置为1
(受限)。检查/proc/sys/fs/protected_hardlinks
确定。
改名
file1所在目录权限为:
drwx------. 18 student student 4096 Dec 27 18:42 .
我能够将其重命名
file1
为file2
,所以我猜测,与复制相同,读取权限others
正在使这种情况发生?
为一个改名,您只需要w
对您拥有的目录具有 rite 权限。您永远不会触及该文件的内容,因此其权限无关紧要。
移动
最后,我无法搬到
file2
其他地方。为什么?
这取决于什么,确切地,你说的“移动”是什么意思,确切地,你的意思是“不同的位置”,以及什么,确切地你的意思是“不能”。
有两种方式可以解释“移动”:
- 删除原始内容并以不同的名称重新创建相同的内容。
- 删除源目录中的链接并在目标目录中创建链接。
如果您使用该mv
实用程序,它实际上可以执行其中任何一个操作,所以让我们看看它们。
#2 只是重命名:您需要w
对源目录具有 rite 权限,以便可以删除链接,并且需要w
对目标目录具有 rite 权限,以便可以创建链接。您在任何时候都不需要触摸该文件或访问其内容,因此权限无关紧要。事实上,将为此mv
使用系统调用。rename
mv
只要有可能,就会尝试做#2。
那么,#2 是什么时候不是可能的?好吧,请记住 FSN 是唯一的在一个文件系统内。还,文件只存在在文件系统内。
因此,应该清楚的是,只有当源目录和目标目录相同时,#2 才是可能的在同一个文件系统上。如果它们位于不同的文件系统上,mv
则会复制文件到目标,然后取消原始文件的链接。这意味着,正如我们上面讨论的,除了w
对源目录的 rite 访问和w
对目标目录的 rite 访问之外,还需要r
对原始文件进行 ead 访问。
执行权限
注意:到目前为止,我们只查看了r
ead 和w
rite 权限,但我们完全忽略了 e x
ecute 权限。
...对于常规文件
对于常规文件,e x
ecute 权限相当明显:它授予执行该文件的权限。 (不,真的吗?)但是,请注意“执行”在这里有特定的含义:它的意思是“将其传递给内核来执行”。
特别是,你做不是需要 ex
执行权限才能将文件传递给脚本解释器。因此,如果您有一个以名为 MyLanguage 的虚构语言调用的脚本文件,myscript
如下所示:
#!/usr/bin/env mylanguage
print "Hello, World!"
然后你做x
如果您像这样执行它,则需要 e ecute 权限:
/path/to/myscript
但你做了不是x
如果您像这样执行它,则需要 e ecute 权限:
mylanguage /path/to/myscript
语言解释器只需要r
读权限,就可以读取脚本文件的内容。
或者,更准确地说,系统不需要您获得电子x
许可,但需要mylanguage
口译员,可以,如果需要,请检查您是否有 e x
ecute 权限。事实上,有些口译员会这样做,有些则不会。
...对于目录
e x
ecute 权限对于目录意味着什么?这里正在执行什么?
对于目录,e x
ecute 权限被解释为“输入”权限或“查找”权限。换句话说,e x
ecute 权限允许您向目录请求 FSN(给定名称)。
您可以将目录视为一个非常简单的程序,它需要姓名作为参数并返回FSN,那么“e ecute Permission”的想法x
就有点道理了。但这确实是一个非常费力的想法。只需忽略x
e ecute 的代表这一事实x
,并考虑x
目录的“查找”或“输入”含义。
其他类型的特殊文件
目录并不是唯一的特殊文件类型。还有其他五个:
- 符号链接,
- 管道,
- 插座,
- 字符特殊文件, 和
- 阻止特殊文件。
符号链接
在这五种中,您最常遇到的是符号链接或者符号链接。
符号链接本质上是一个包含小路。在非常早期、非常简单的 Unix 文件系统中,符号链接实际上只是包含路径的文本文件。今天你或多或少仍然会这样看待它们。
一旦理解了这一点,就应该清楚,为了创建到某个地方的符号链接,您需要做的就是创建文件。您不需要访问放入文件中的路径。事实上,这条路甚至不必存在!
例如,假设您被允许创建文件,您可以轻松地执行
ln -s https://www.google.com/ google
这是一个完全有效的符号链接:google
是一个完全有效的名称,也是一个完全有效的路径(它的意思是“在当前目录中指定的目录中https://www.google.com/
指定的目录),但它当然不是指向实际存在的文件,尽管您www.google.com
https:
可以做
mkdir -p https:/www.google.com
如果您愿意,可以让它指向某个地方:
cd google
# no error
答案2
所以我猜测其他人的读取权限使得复制成为可能?
复制文件只是读取文件内容,创建一个新文件,然后将数据写入其中。您需要读取原始文件的权限,以及对新文件的目录的写入权限才能创建它。看执行与读取位。 Linux 中的目录权限如何工作?
是什么阻止了硬链接的创建?
大概是fs.protected_hardlinks
sysctl,提到的硬链接创建 - 权限?。如果设置,则仅当您拥有该文件或具有对该文件的读写权限以及对新链接的目录的写访问权限时,才可以创建硬链接。如果未设置,您只需要对新链接的目录具有写权限。
符号链接有一个类似的旋钮,fs.protected_hardlinks
.两者都是为了阻止特权进程遵循可能被非特权进程修改的链接的各种漏洞,例如/tmp
.旋钮是中描述的proc(5)
手册页。
正如评论中提到的,符号链接/硬链接保护可能在大多数常见的 Linux 发行版中默认启用。
我能够将 file1 重命名为 file2 所以我猜测,与复制相同,其他人的读取权限正在使这种情况发生?
最后,我无法将 file2 移动到其他位置。为什么?
在单个文件系统中移动文件与重命名它相同。您需要对旧目录和新目录都有写权限,并且如果移动目录,对目录本身的写权限。 (跨文件系统“移动”文件需要创建一个新文件,复制内容并删除原始文件。)rename()
系统调用的手册页至少描述了 EACCES 和 EPERM 错误的描述中的一些要求。
这里的共同主题是目录的数据是文件名,(或“硬”链接),然后指向描述实际的索引节点文件。目录的访问权限控制对该数据的访问,因此会更改文件名。因此,创建、删除、移动和重命名文件需要对包含受影响文件名的一个或多个目录具有写权限。
x
在所有情况下,您还需要对受影响的文件/文件名路径上的所有目录具有搜索/访问权限(位)。 (看path_resolution(7)
)
答案3
硬链接链接到文件的存储并且将具有相同的索引节点。因此,除非“其他人”具有写入权限,否则您不能进行硬链接。
如果文件的权限为 646,您就可以硬链接到该文件。最后,输入硬链接和原始文件的 ls -i 文件名。您将看到它们具有相同的索引节点。