lkml.org 
[lkml]   [2021]   [Nov]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH 2/2] xfs: make sure link path does not go away at access
From
Date
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;
}

diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index a607d6aca5c4..2977e19da7b7 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -524,11 +524,17 @@ xfs_vn_get_link_inline(

/*
* The VFS crashes on a NULL pointer, so return -EFSCORRUPTED if
- * if_data is junk.
+ * if_data is junk. Also, if the path walk is in rcu-walk mode
+ * and the inode link path has gone away due inode re-use we have
+ * no choice but to tell the VFS to redo the lookup.
*/
- link = ip->i_df.if_u1.if_data;
+ link = rcu_dereference(ip->i_df.if_u1.if_data);
+ if (!dentry && !link)
+ return ERR_PTR(-ECHILD);
+
if (XFS_IS_CORRUPT(ip->i_mount, !link))
return ERR_PTR(-EFSCORRUPTED);
+
return link;
}


\
 
 \ /
  Last update: 2021-11-11 04:40    [W:0.124 / U:0.028 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site