Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 为什么rename()系统调用禁止移动我可以';你不能写入其他目录吗?_Unix_Filesystems_System Calls - Fatal编程技术网

Unix 为什么rename()系统调用禁止移动我可以';你不能写入其他目录吗?

Unix 为什么rename()系统调用禁止移动我可以';你不能写入其他目录吗?,unix,filesystems,system-calls,Unix,Filesystems,System Calls,我试图理解为什么这个设计决策是在4.2BSD中使用rename()系统调用做出的。这里没有我想要解决的问题,只是理解行为本身的基本原理 4.2BSD引入了rename()系统调用,以允许文件的原子重命名/移动。从4.3BSD-Reno/src/sys/ufs/ufs_vnops.c开始: /* * If ".." must be changed (ie the directory gets a new * parent) then the source directory must n

我试图理解为什么这个设计决策是在4.2BSD中使用rename()系统调用做出的。这里没有我想要解决的问题,只是理解行为本身的基本原理

4.2BSD引入了rename()系统调用,以允许文件的原子重命名/移动。从4.3BSD-Reno/src/sys/ufs/ufs_vnops.c开始:

 /*
  * If ".." must be changed (ie the directory gets a new
  * parent) then the source directory must not be in the
  * directory heirarchy above the target, as this would
  * orphan everything below the source directory. Also
  * the user must have write permission in the source so
  * as to be able to change "..". We must repeat the call 
  * to namei, as the parent directory is unlocked by the
  * call to checkpath().
  */

 if (oldparent != dp->i_number)
  newparent = dp->i_number;
 if (doingdirectory && newparent) {
  VOP_LOCK(fndp->ni_vp);
  error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred);
  VOP_UNLOCK(fndp->ni_vp);
很明显,这张支票是故意加上去的。我的问题是——为什么?这种行为应该是直觉的吗

这样做的效果是,一个人无法将一个无法写入的目录(位于一个可以写入的目录中)移动到另一个可以原子方式写入的目录。但是,您可以创建一个新目录,将链接移到上面(假设您对该目录具有读取权限),然后删除该目录上的写入位。你就是不能原子化

% cd /tmp
% mkdir stackoverflow-question
% cd stackoverflow-question
% mkdir directory-1
% mkdir directory-2
% mkdir directory-1/directory-i-cant-write
% echo "foo" > directory-1/directory-i-cant-write/contents
% chmod 000 directory-1/directory-i-cant-write/contents
% chmod 000 directory-1/directory-i-cant-write
% mv directory-1/directory-i-cant-write directory-2
mv: rename directory-1/directory-i-cant-write to directory-2/directory-i-cant-write: Permission denied
我们现在有一个目录,我不能写,我不能读,我不能原子移动的内容。但是,我可以通过更改权限、创建新目录、使用ln创建新链接以及更改权限,以非原子方式实现相同的效果。(留给读者作为练习)

。和。。已经是特例了,所以我并不特别相信如果我不能写一个目录,我就不能“更改…”这是源代码所建议的。除了代码作者认为正确的行为之外,还有其他原因吗?如果我们让人们在他们可以写的目录之间以原子方式移动目录(他们不能写),会发生什么不好的事情吗 用户必须在源中具有写入权限,因此 以便能够更改“.”


换句话说,为了使目录在移动后格式良好,您必须更改。。链接在它里面,你没有权限这样做。因此,这只是权限方案的一个逻辑部分,尽管不是一个非常明显的部分。

存在许多专门的程序,允许非特权用户在某些狭义定义的条件下执行某些通常具有特权的操作。此类程序通常使用setuid标志工作。在程序中,它检查以确保满足特殊条件,如果满足,则执行特权操作

有时有必要按名称引用文件,例如,如果要执行的程序以文件名为参数。如果必须首先执行检查,如果在检查时间和使用时间之间,未经授权的用户可以重命名路径名的任何部分,则这可能导致危险的竞争条件。有时可以通过要求包含每个指定路径组件的目录对非特权用户没有写权限来解决这一问题,确保在此期间非特权用户不能重命名(或取消链接并重新创建)任何路径组件以引用与检查内容不同的内容。如果一个无权限的用户即使没有该目录中的写入权限也可以更改“.”所指的内容,这将创建一个安全漏洞。如果这是内核允许的特殊异常,那么进行此类检查的每个程序都必须专门检查“.”组件以避免此问题


此外,更新目录中的“.”需要写入该目录的数据块,并且还将更新该目录的上次修改时间,至少在传统的Unix和BSD文件系统上是这样(我知道Apple HFS+的情况并非如此,其中“.”是合成的)。从直觉上看,关闭其他用户的写入权限将禁止他们写入目录或更改其上次修改时间的任何操作。

我认为Andrew McGregor很可能是对的。不一定UFS必须以这种方式工作,但实现者(Kirk McKusick)只是扩展了文件系统权限的逻辑以涵盖这种情况。因此,如果您没有对目标目录的写入权限,则不能更改其“.”条目

但在看你的例子时,我想到了另一种可能性。这可能不是像您所展示的那样,单个用户拥有所有相关目录的情况,而是目录由不同用户拥有的情况。换句话说,此检查阻止我在具有写入权限的父目录之间移动您拥有的目录。当然,假设您没有给我在您的目录中的写入权限

诚然,在正常使用中,出现这种情况的场景很少。但是内核必须担心所有奇怪的用例以及常见的用例


一个明显的反论点是,如果我们想担心这种情况,那么我们还想阻止人们在他们有写权限的目录之间移动他们不拥有的文件…

除非,当您查看代码时,您会看到它专门为此做写检查(对ufs_访问的调用)-这是一段代码,意味着您需要能够编写一个要更改的目录。。所以我相信你的答案是循环推理,不是吗?每个目录都包含一个。。林克,是吗?该链接位于目录中,因此更改它需要写入权限。但是移动目录需要。。因此,您需要对目录的写入权限才能移动它。您自己查看ufs_vnops.c并查看可能会有所帮助。要更新的代码。。是重命名系统调用的一部分,实现rename()时要做的最简单的事情是在实际编写之前不必检查写权限。记住,我们在内核中,而不是在用户空间中——这取决于我们是否被允许做我们正在尝试的事情。如果这种行为