lkml.org 
[lkml]   [2022]   [Jan]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 025/171] fsnotify: fix fsnotify hooks in pseudo filesystems
    Date
    From: Amir Goldstein <amir73il@gmail.com>

    commit 29044dae2e746949ad4b9cbdbfb248994d1dcdb4 upstream.

    Commit 49246466a989 ("fsnotify: move fsnotify_nameremove() hook out of
    d_delete()") moved the fsnotify delete hook before d_delete() so fsnotify
    will have access to a positive dentry.

    This allowed a race where opening the deleted file via cached dentry
    is now possible after receiving the IN_DELETE event.

    To fix the regression in pseudo filesystems, convert d_delete() calls
    to d_drop() (see commit 46c46f8df9aa ("devpts_pty_kill(): don't bother
    with d_delete()") and move the fsnotify hook after d_drop().

    Add a missing fsnotify_unlink() hook in nfsdfs that was found during
    the audit of fsnotify hooks in pseudo filesystems.

    Note that the fsnotify hooks in simple_recursive_removal() follow
    d_invalidate(), so they require no change.

    Link: https://lore.kernel.org/r/20220120215305.282577-2-amir73il@gmail.com
    Reported-by: Ivan Delalande <colona@arista.com>
    Link: https://lore.kernel.org/linux-fsdevel/YeNyzoDM5hP5LtGW@visor/
    Fixes: 49246466a989 ("fsnotify: move fsnotify_nameremove() hook out of d_delete()")
    Cc: stable@vger.kernel.org # v5.3+
    Signed-off-by: Amir Goldstein <amir73il@gmail.com>
    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/configfs/dir.c | 6 +++---
    fs/devpts/inode.c | 2 +-
    fs/nfsd/nfsctl.c | 5 +++--
    net/sunrpc/rpc_pipe.c | 4 ++--
    4 files changed, 9 insertions(+), 8 deletions(-)

    --- a/fs/configfs/dir.c
    +++ b/fs/configfs/dir.c
    @@ -1780,8 +1780,8 @@ void configfs_unregister_group(struct co
    configfs_detach_group(&group->cg_item);
    d_inode(dentry)->i_flags |= S_DEAD;
    dont_mount(dentry);
    + d_drop(dentry);
    fsnotify_rmdir(d_inode(parent), dentry);
    - d_delete(dentry);
    inode_unlock(d_inode(parent));

    dput(dentry);
    @@ -1922,10 +1922,10 @@ void configfs_unregister_subsystem(struc
    configfs_detach_group(&group->cg_item);
    d_inode(dentry)->i_flags |= S_DEAD;
    dont_mount(dentry);
    - fsnotify_rmdir(d_inode(root), dentry);
    inode_unlock(d_inode(dentry));

    - d_delete(dentry);
    + d_drop(dentry);
    + fsnotify_rmdir(d_inode(root), dentry);

    inode_unlock(d_inode(root));

    --- a/fs/devpts/inode.c
    +++ b/fs/devpts/inode.c
    @@ -621,8 +621,8 @@ void devpts_pty_kill(struct dentry *dent

    dentry->d_fsdata = NULL;
    drop_nlink(dentry->d_inode);
    - fsnotify_unlink(d_inode(dentry->d_parent), dentry);
    d_drop(dentry);
    + fsnotify_unlink(d_inode(dentry->d_parent), dentry);
    dput(dentry); /* d_alloc_name() in devpts_pty_new() */
    }

    --- a/fs/nfsd/nfsctl.c
    +++ b/fs/nfsd/nfsctl.c
    @@ -1249,7 +1249,8 @@ static void nfsdfs_remove_file(struct in
    clear_ncl(d_inode(dentry));
    dget(dentry);
    ret = simple_unlink(dir, dentry);
    - d_delete(dentry);
    + d_drop(dentry);
    + fsnotify_unlink(dir, dentry);
    dput(dentry);
    WARN_ON_ONCE(ret);
    }
    @@ -1340,8 +1341,8 @@ void nfsd_client_rmdir(struct dentry *de
    dget(dentry);
    ret = simple_rmdir(dir, dentry);
    WARN_ON_ONCE(ret);
    + d_drop(dentry);
    fsnotify_rmdir(dir, dentry);
    - d_delete(dentry);
    dput(dentry);
    inode_unlock(dir);
    }
    --- a/net/sunrpc/rpc_pipe.c
    +++ b/net/sunrpc/rpc_pipe.c
    @@ -600,9 +600,9 @@ static int __rpc_rmdir(struct inode *dir

    dget(dentry);
    ret = simple_rmdir(dir, dentry);
    + d_drop(dentry);
    if (!ret)
    fsnotify_rmdir(dir, dentry);
    - d_delete(dentry);
    dput(dentry);
    return ret;
    }
    @@ -613,9 +613,9 @@ static int __rpc_unlink(struct inode *di

    dget(dentry);
    ret = simple_unlink(dir, dentry);
    + d_drop(dentry);
    if (!ret)
    fsnotify_unlink(dir, dentry);
    - d_delete(dentry);
    dput(dentry);
    return ret;
    }

    \
     
     \ /
      Last update: 2022-01-31 12:40    [W:4.039 / U:0.084 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site