Re: [QUESTION] question about the errno of rename the parent dir to a subdir of a specified directory

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Thanks for your detailed explanation, I will also check the freeBSD.

Thanks,
Yi.

On 2019/12/26 0:27, Al Viro wrote:
> On Wed, Dec 25, 2019 at 09:16:09PM +0800, zhangyi (F) wrote:
>> Hi,
>>
>> If we rename the parent-dir to a sub-dir of a specified directory, the
>> rename() syscall return -EINVAL because lock_rename() in lock_rename()
>> checks the relations of the sorece and dest dirs. But if the 'parent'
>> dir is a mountpoint, the rename() syscall return -EXDEV instead because
>> it checks the parent dir's mountpoint of the sorece and dest dirs.
>>
>> For example:
>> Case 1: rename() return -EINVAL
>> # mkdir -p parent/dir
>> # rename parent parent/dir/subdir parent
>> rename: parent: rename to parent/dir/subdir failed: Invalid argument
> 
> That was rename("parent", "parent/dir/subdir") being told to sod off and
> not try to create loops.
> 
>> Case 2: rename() return -EXDEV
>> # mkdir parent
>> # mount -t tmpfs test parent
>> # mkdir parent/dir
>> # rename parent parent/dir/subdir parent
>> rename: parent: rename to parent/dir/subdir failed: Invalid cross-device link
>>
>> In case 2, although 'parent' directory is a mountpoint, it acted as a root
>> dir of the "test tmpfs", so it should belongs to the same mounted fs of
>> 'dir' directoty, so I think it shall return -EINVAL.
>>
>> Is it a bug or just designed as this ?
> 
> rename() operates on directory entries.  Pathnames can refer to files (including
> directories) or they can refer to directory entries (links).  rename() and other
> directory-modifying syscalls operate on the latter.  In the second test two
> error conditions apply: in addition to attempted loop creation, we are asked to
> move the link 'parent' from whatever it's in (your current directory) to 'subdir'
> in the directory parent/dir, the latter being on a different filesystem.
> 
> It's not "take the file old pathname refers to, move it to new place"; that's
> particularly obvious when you consider
> 
> echo foo >a	# create a file
> ln a b		# now 'a' and 'b' both refer to it
> mv a c		# or rename a c a, if you really want to touch util-linux rename(1)
> 
> Desired result is, of course, 'a' disappearing, 'b' left as is and 'c' now refering
> to the same file.  If you did mv b c as the last step, 'a' would be left as is,
> 'b' would disappear and 'c' added, refering to the same file.  But the only
> difference between mv a c and mv b c is the first argument of rename(2) and
> in both cases it resolves to the same file.  In other words, rename(2) can't
> operate on that level; to be of any use it has to interpret the pathnames
> as refering to directory entries.
> 
> That, BTW, is the source of "the last component must not be . or .." - they
> do refer to directories just fine, but rename("dir1/.", "dir2/foo") is not just
> 'make the directory refered to by "dir1/." show up as "dir2/foo"' - it's
> 'rip the entry "." from the directory "dir1" and move it into directory "dir2"
> under the name "foo"'.
> 
> So your second testcase is a genuine cross-filesystem move; you want a link
> to disappear from a directory on one filesystem and reappear in a directory
> on another.  It doesn't matter what's mounted on top of that - directory
> entry refers to the mountpoint, not the thing mounted on it.
> 
> And in cases when more than one error condition applies, portable userland
> should be ready to cope with the operating system returning any of those.
> Different Unices might return different applicable errors.  In this particular
> case I would expect EXDEV to take precedence on the majority of implementations,
> but that's not guaranteed.  Note, BTW, that there might be other errors
> applicable here and it's a sufficiently dark corner to expect differences
> (e.g. there might be a blanket ban on renaming mountpoints in general,
> POSIX being quiet on that topic be damned).  
> 
> That actually might be a good way to get into given Unix VFS - figuring out
> what happens in this implementation will tell you a lot about its pathname
> resolution, related kernel data structures and locking involved.  Might
> send you away screaming, though - rename(2) is usually the worst part
> as it is, and bringing the mountpoint crossing into the game is likely
> to expose all kinds of interesting corner cases.
> 
> .
> 




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux