Re: [PATCH] fnotify: invalidate dcache before IN_DELETE event

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

 



On Tue, Jan 18, 2022 at 2:00 PM Amir Goldstein <amir73il@xxxxxxxxx> wrote:
>
> Apparently, there are some applications that use IN_DELETE event as an
> invalidation mechanism and expect that if they try to open a file with
> the name reported with the delete event, that it should not contain the
> content of the deleted file.
>
> 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, we use two different techniques:
> 1) For call sites that call d_delete() with elevated refcount, convert
>    the call to d_drop() and move the fsnotify hook after d_drop().
> 2) For the vfs helpers that may turn dentry to negative on d_delete(),
>    use a helper d_delete_notify() to pin the inode, so we can pass it
>    to an fsnotify hook after d_delete().
>
> Create a new hook fsnotify_delete() that allows to pass a negative
> dentry and takes the unlinked inode as an argument.
>
> Add a missing fsnotify_unlink() hook in nfsdfs that was found during
> the call sites audit.
>
> Note that the call sites in simple_recursive_removal() follow
> d_invalidate(), so they require no change.
>
> Backporting hint: this regression is from v5.3. Although patch will
> apply with only trivial conflicts to v5.4 and v5.10, it won't build,
> because fsnotify_delete() implementation is different in each of those
> versions (see fsnotify_link()).
>
> Reported-by: Ivan Delalande <colona@xxxxxxxxxx>
> Link: https://lore.kernel.org/linux-fsdevel/YeNyzoDM5hP5LtGW@visor/
> Fixes: 49246466a989 ("fsnotify: move fsnotify_nameremove() hook out of d_delete()")
> Cc: stable@xxxxxxxxxxxxxxx # v5.3+
> Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
> ---
>
> Jan,
>
> This turned into an audit of fsnotify_unlink/rmdir() call sites, so
> besides fixing the regression, I also added one missing hook and replaced
> most of the d_delete() calls with d_drop() to simplify things.
>
> I will follow up with backports for v5.4 and v5.10 and will send the
> repro to LTP guys.
>
> Thanks,
> Amir.
>
>  fs/btrfs/ioctl.c         |  5 ++---
>  fs/configfs/dir.c        |  6 +++---
>  fs/devpts/inode.c        |  2 +-
>  fs/namei.c               | 27 ++++++++++++++++++++++-----
>  fs/nfsd/nfsctl.c         |  5 +++--
>  include/linux/fsnotify.h | 20 ++++++++++++++++++++
>  net/sunrpc/rpc_pipe.c    |  4 ++--
>  7 files changed, 53 insertions(+), 16 deletions(-)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index edfecfe62b4b..121e8f439996 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -3060,10 +3060,9 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
>         btrfs_inode_lock(inode, 0);
>         err = btrfs_delete_subvolume(dir, dentry);
>         btrfs_inode_unlock(inode, 0);
> -       if (!err) {
> +       d_drop(dentry);
> +       if (!err)
>                 fsnotify_rmdir(dir, dentry);
> -               d_delete(dentry);
> -       }
>

oops that an unintentional logic change.
Was supposed to be:

        if (!err) {
+               d_drop(dentry);
                fsnotify_rmdir(dir, dentry);
-               d_delete(dentry);
        }

Anyway, fix is pushed to fsnotify-fixes branch.

Thanks,
Amir.



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux