lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <DB6PR0102MB2630902B2569060CD5E802EA88999@DB6PR0102MB2630.eurprd01.prod.exchangelabs.com>
Date:   Tue, 2 Mar 2021 09:02:16 +0000
From:   Diego Santa Cruz <Diego.SantaCruz@...netix.com>
To:     Trond Myklebust <trond.myklebust@...merspace.com>,
        "anna.schumaker@...app.com" <anna.schumaker@...app.com>
CC:     "linux-nfs@...r.kernel.org" <linux-nfs@...r.kernel.org>,
        "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
Subject: symlinkat() behavior with NFS depends on dentry being on cache or not

Hello,

[resending as plain-text, sorry for the noise]

I noticed that the symlinkat() syscall changes behavior when the newpath (i.e. link name) has a trailing slash and is the path to a directory residing on NFS depending on this path being in the dentry cache or not. I stumbled upon this in the context of a Yocto / OE-Core system where I updated coreutils from version 8.30 to 8.31. This creates problems with ln in coreutils in 8.31. I am currently using kernel 5.4.90.

What I observe is that sylinkat("name", AT_FDCWD, "/path/to/nfs/existing/dir/") returns ENOENT when "/path/to/nfs/existing/dir/" is not in the dentry cache but EEXIST when it is, but only when "/path/to/nfs/existing/dir/" is on NFS (NFSv3 in my case). Note that if I remove the trailing slash from the newpath argument then it returns EEXIST in all cases.

Following change https://github.com/coreutils/coreutils/commit/571f63f5010b047a8a3250304053f05949faded4 in coreutils this makes "ln -sf name /path/to/nfs/existing/dir/" sometimes fail with a "cannot overwrite directory" error (when the path is not in the dentry cache). There was no problem before this change because ln did a stat of the link name path before calling symlinkat, so the entry was in the dentry cache when symlinkat executes.

I have created a simple program to reproduce this more easily, which I have attached.

To reproduce do this.
  - Compile the attached symlinkat.c
  - Mount a NFSv3 filesystem at /mnt
  - mkdir /mnt/test
  - To test the error with no dentry cache and trailing slash:
    sync; echo 3 > /proc/sys/vm/drop_caches; ./symlinkat name /mnt/test/
    symlinkat name /mnt/test/ failed: No such file or directory (2)
  - To test with the dentry cache:
    ls -d /mnt/test/; ./symlinkat name /mnt/test/
    symlinkat name /mnt/test/ failed: File exists (17)
  - To test the error with no dentry cache and no trailing slash:
    sync; echo 3 > /proc/sys/vm/drop_caches; ./symlinkat name /mnt/test
    symlinkat name /mnt/test failed: File exists (17)

Although I'm no kernel expert, from what I've understood of the kernel code this seems to be a bad interaction between the generic fs handling in fs/namei.c and the NFS client implementation. The filename_create() function will call __lookup_hash() after setting LOOKUP_EXCL in the flags and if there is no dentry cache for the path then nfs_lookup() will be called, will notice this flag in the nfs_is_exclusive_create() test, optimize away the lookup and not fill d_inode in the dentry. When execution returns to filename_create() the special casing will notice that is_dir is not set and last.name has a trailing slash and thus returns ENOENT. Looking for LOOKUP_EXCL usage in the kernel only NFS does this kind of optimization in current kernels, but in 3.5 and older the same optimization was also done by CIFS.

According to the symlink and symlinkat man pages ENOENT is returned when a directory component of newpath does not exist or is a dangling symbolic link, which is not the case here.

What would be the best course of action to address this issue?

Thanks,

Diego
-- 
Diego Santa Cruz, PhD
Technology Architect
spinetix.com


View attachment "symlinkat.c" of type "text/plain" (497 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ