public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Dave Chinner <david@fromorbit.com>
To: Ian Kent <raven@themaw.net>
Cc: xfs <linux-xfs@vger.kernel.org>,
	"Darrick J. Wong" <djwong@kernel.org>,
	Miklos Szeredi <miklos@szeredi.hu>,
	Brian Foster <bfoster@redhat.com>,
	Al Viro <viro@zeniv.linux.org.uk>,
	David Howells <dhowells@redhat.com>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>,
	Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 2/2] xfs: make sure link path does not go away at access
Date: Fri, 12 Nov 2021 11:32:49 +1100	[thread overview]
Message-ID: <20211112003249.GL449541@dread.disaster.area> (raw)
In-Reply-To: <163660197073.22525.11235124150551283676.stgit@mickey.themaw.net>

On Thu, Nov 11, 2021 at 11:39:30AM +0800, Ian Kent wrote:
> When following a trailing symlink in rcu-walk mode it's possible to
> succeed in getting the ->get_link() method pointer but the link path
> string be deallocated while it's being used.
> 
> Utilize the rcu mechanism to mitigate this risk.
> 
> Suggested-by: Miklos Szeredi <miklos@szeredi.hu>
> Signed-off-by: Ian Kent <raven@themaw.net>
> ---
>  fs/xfs/kmem.h      |    4 ++++
>  fs/xfs/xfs_inode.c |    4 ++--
>  fs/xfs/xfs_iops.c  |   10 ++++++++--
>  3 files changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h
> index 54da6d717a06..c1bd1103b340 100644
> --- a/fs/xfs/kmem.h
> +++ b/fs/xfs/kmem.h
> @@ -61,6 +61,10 @@ static inline void  kmem_free(const void *ptr)
>  {
>  	kvfree(ptr);
>  }
> +static inline void  kmem_free_rcu(const void *ptr)
> +{
> +	kvfree_rcu(ptr);
> +}
>  
>  
>  static inline void *
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index a4f6f034fb81..aaa1911e61ed 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -2650,8 +2650,8 @@ xfs_ifree(
>  	 * already been freed by xfs_attr_inactive.
>  	 */
>  	if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
> -		kmem_free(ip->i_df.if_u1.if_data);
> -		ip->i_df.if_u1.if_data = NULL;
> +		kmem_free_rcu(ip->i_df.if_u1.if_data);
> +		RCU_INIT_POINTER(ip->i_df.if_u1.if_data, NULL);
>  		ip->i_df.if_bytes = 0;
>  	}

How do we get here in a way that the VFS will walk into this inode
during a lookup?

I mean, the dentry has to be validated and held during the RCU path
walk, so if we are running a transaction to mark the inode as free
here it has already been unlinked and the dentry turned
negative. So anything that is doing a lockless pathwalk onto that
dentry *should* see that it is a negative dentry at this point and
hence nothing should be walking any further or trying to access the
link that was shared from ->get_link().

AFAICT, that's what the sequence check bug you fixed in the previous
patch guarantees. It makes no difference if the unlinked inode has
been recycled or not, the lookup race condition is the same in that
the inode has gone through ->destroy_inode and is now owned by the
filesystem and not the VFS.

Otherwise, it might just be best to memset the buffer to zero here
rather than free it, and leave it to be freed when the inode is
freed from the RCU callback in xfs_inode_free_callback() as per
normal.

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

  parent reply	other threads:[~2021-11-12  0:33 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-11  3:39 [PATCH 1/2] vfs: check dentry is still valid in get_link() Ian Kent
2021-11-11  3:39 ` [PATCH 2/2] xfs: make sure link path does not go away at access Ian Kent
2021-11-11 16:08   ` Brian Foster
2021-11-11 23:10     ` Ian Kent
2021-11-12 11:47       ` Brian Foster
2021-11-13  5:17         ` Ian Kent
2021-11-12  0:32   ` Dave Chinner [this message]
2021-11-12  1:26     ` Ian Kent
2021-11-12  7:23     ` Miklos Szeredi
2021-11-14 23:18       ` Dave Chinner
2021-11-15  9:21         ` Miklos Szeredi
2021-11-15 22:24           ` Dave Chinner
2021-11-16  1:03             ` Ian Kent
2021-11-16  3:01               ` Dave Chinner
2021-11-16 10:12                 ` Miklos Szeredi
2021-11-16 16:04                   ` Brian Foster
2021-11-16 13:38                 ` Ian Kent
2021-11-16 15:59                 ` Brian Foster
2021-11-17  0:22                   ` Dave Chinner
2021-11-17  2:19                     ` Ian Kent
2021-11-17 21:06                       ` Dave Chinner
2021-11-17 18:56                     ` Brian Foster
2021-11-17 21:48                       ` Dave Chinner
2021-11-19 19:44                         ` Brian Foster
2021-11-22  0:08                           ` Dave Chinner
2021-11-22 19:27                             ` Brian Foster
2021-11-22 23:26                               ` Dave Chinner
2021-11-24 20:56                                 ` Brian Foster
2021-12-15  3:54                                   ` Ian Kent
2021-12-15  5:06                                     ` Darrick J. Wong
2021-12-16  2:45                                       ` Ian Kent
2021-11-17 20:38   ` kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211112003249.GL449541@dread.disaster.area \
    --to=david@fromorbit.com \
    --cc=bfoster@redhat.com \
    --cc=dhowells@redhat.com \
    --cc=djwong@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=raven@themaw.net \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox