|
Kmods SIG |
c540c3 |
From 762c69685ff7ad5ad7fee0656671e20a0c9c864d Mon Sep 17 00:00:00 2001
|
|
Kmods SIG |
c540c3 |
From: Al Viro <viro@zeniv.linux.org.uk>
|
|
Kmods SIG |
c540c3 |
Date: Sun, 3 Nov 2019 13:55:43 -0500
|
|
Kmods SIG |
c540c3 |
Subject: [Backport 762c69685ff7] ecryptfs_lookup_interpose():
|
|
Kmods SIG |
c540c3 |
lower_dentry->d_parent is not stable either
|
|
Kmods SIG |
c540c3 |
|
|
Kmods SIG |
c540c3 |
We need to get the underlying dentry of parent; sure, absent the races
|
|
Kmods SIG |
c540c3 |
it is the parent of underlying dentry, but there's nothing to prevent
|
|
Kmods SIG |
c540c3 |
losing a timeslice to preemtion in the middle of evaluation of
|
|
Kmods SIG |
c540c3 |
lower_dentry->d_parent->d_inode, having another process move lower_dentry
|
|
Kmods SIG |
c540c3 |
around and have its (ex)parent not pinned anymore and freed on memory
|
|
Kmods SIG |
c540c3 |
pressure. Then we regain CPU and try to fetch ->d_inode from memory
|
|
Kmods SIG |
c540c3 |
that is freed by that point.
|
|
Kmods SIG |
c540c3 |
|
|
Kmods SIG |
c540c3 |
dentry->d_parent *is* stable here - it's an argument of ->lookup() and
|
|
Kmods SIG |
c540c3 |
we are guaranteed that it won't be moved anywhere until we feed it
|
|
Kmods SIG |
c540c3 |
to d_add/d_splice_alias. So we safely go that way to get to its
|
|
Kmods SIG |
c540c3 |
underlying dentry.
|
|
Kmods SIG |
c540c3 |
|
|
Kmods SIG |
c540c3 |
Cc: stable@vger.kernel.org # since 2009 or so
|
|
Kmods SIG |
c540c3 |
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Kmods SIG |
c540c3 |
---
|
|
Kmods SIG |
c540c3 |
src/inode.c | 7 +++----
|
|
Kmods SIG |
c540c3 |
1 file changed, 3 insertions(+), 4 deletions(-)
|
|
Kmods SIG |
c540c3 |
|
|
Kmods SIG |
c540c3 |
diff --git a/src/inode.c b/src/inode.c
|
|
Kmods SIG |
c540c3 |
index 3c229872135987fb4d0a1a36a910651d5f37a08b..e23752d9a79f3d255345177db1b66950ae8e6607 100644
|
|
Kmods SIG |
c540c3 |
--- a/src/inode.c
|
|
Kmods SIG |
c540c3 |
+++ b/src/inode.c
|
|
Kmods SIG |
c540c3 |
@@ -319,9 +319,9 @@ static int ecryptfs_i_size_read(struct dentry *dentry, struct inode *inode)
|
|
Kmods SIG |
c540c3 |
static struct dentry *ecryptfs_lookup_interpose(struct dentry *dentry,
|
|
Kmods SIG |
c540c3 |
struct dentry *lower_dentry)
|
|
Kmods SIG |
c540c3 |
{
|
|
Kmods SIG |
c540c3 |
+ struct path *path = ecryptfs_dentry_to_lower_path(dentry->d_parent);
|
|
Kmods SIG |
c540c3 |
struct inode *inode, *lower_inode;
|
|
Kmods SIG |
c540c3 |
struct ecryptfs_dentry_info *dentry_info;
|
|
Kmods SIG |
c540c3 |
- struct vfsmount *lower_mnt;
|
|
Kmods SIG |
c540c3 |
int rc = 0;
|
|
Kmods SIG |
c540c3 |
|
|
Kmods SIG |
c540c3 |
dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL);
|
|
Kmods SIG |
c540c3 |
@@ -330,13 +330,12 @@ static struct dentry *ecryptfs_lookup_interpose(struct dentry *dentry,
|
|
Kmods SIG |
c540c3 |
return ERR_PTR(-ENOMEM);
|
|
Kmods SIG |
c540c3 |
}
|
|
Kmods SIG |
c540c3 |
|
|
Kmods SIG |
c540c3 |
- lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
|
|
Kmods SIG |
c540c3 |
fsstack_copy_attr_atime(d_inode(dentry->d_parent),
|
|
Kmods SIG |
c540c3 |
- d_inode(lower_dentry->d_parent));
|
|
Kmods SIG |
c540c3 |
+ d_inode(path->dentry));
|
|
Kmods SIG |
c540c3 |
BUG_ON(!d_count(lower_dentry));
|
|
Kmods SIG |
c540c3 |
|
|
Kmods SIG |
c540c3 |
ecryptfs_set_dentry_private(dentry, dentry_info);
|
|
Kmods SIG |
c540c3 |
- dentry_info->lower_path.mnt = lower_mnt;
|
|
Kmods SIG |
c540c3 |
+ dentry_info->lower_path.mnt = mntget(path->mnt);
|
|
Kmods SIG |
c540c3 |
dentry_info->lower_path.dentry = lower_dentry;
|
|
Kmods SIG |
c540c3 |
|
|
Kmods SIG |
c540c3 |
/*
|
|
Kmods SIG |
c540c3 |
--
|
|
Kmods SIG |
c540c3 |
2.31.1
|
|
Kmods SIG |
c540c3 |
|