• Trond Myklebust's avatar
    NFS: Don't allow NFS silly-renamed files to be deleted, no signal · 5a7a613a
    Trond Myklebust authored
    Commit 73ca1001 broke the code that prevents the client from deleting
    a silly renamed dentry.  This affected "delete on last close"
    semantics as after that commit, nothing prevented removal of
    silly-renamed files.  As a result, a process holding a file open
    could easily get an ESTALE on the file in a directory where some
    other process issued 'rm -rf some_dir_containing_the_file' twice.
    Before the commit, any attempt at unlinking silly renamed files would
    fail inside may_delete() with -EBUSY because of the
    DCACHE_NFSFS_RENAMED flag.  The following testcase demonstrates
    the problem:
      tail -f /nfsmnt/dir/file &
      rm -rf /nfsmnt/dir
      rm -rf /nfsmnt/dir
      # second removal does not fail, 'tail' process receives ESTALE
    
    The problem with the above commit is that it unhashes the old and
    new dentries from the lookup path, even in the normal case when
    a signal is not encountered and it would have been safe to call
    d_move.  Unfortunately the old dentry has the special
    DCACHE_NFSFS_RENAMED flag set on it.  Unhashing has the
    side-effect that future lookups call d_alloc(), allocating a new
    dentry without the special flag for any silly-renamed files.  As a
    result, subsequent calls to unlink silly renamed files do not fail
    but allow the removal to go through.  This will result in ESTALE
    errors for any other process doing operations on the file.
    
    To fix this, go back to using d_move on success.
    For the signal case, it's unclear what we may safely do beyond d_drop.
    Reported-by: default avatarDave Wysochanski <dwysocha@redhat.com>
    Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
    Acked-by: default avatarJeff Layton <jlayton@redhat.com>
    Cc: stable@vger.kernel.org
    5a7a613a
unlink.c 14.5 KB