|
David Disseldorp |
14422d |
From 76179b4dae212143faa023b71e44554c2854c2c0 Mon Sep 17 00:00:00 2001
|
|
David Disseldorp |
14422d |
From: Zheng Liang <zhengliang6@huawei.com>
|
|
David Disseldorp |
14422d |
Date: Fri, 24 Sep 2021 09:16:27 +0800
|
|
David Disseldorp |
14422d |
Subject: [PATCH] ovl: fix missing negative dentry check in ovl_rename()
|
|
David Disseldorp |
14422d |
Git-commit: a295aef603e109a47af355477326bd41151765b6
|
|
David Disseldorp |
14422d |
Patch-mainline: v5.15-rc5
|
|
David Disseldorp |
14422d |
References: CVE-2021-20321 bsc#1191647
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
The following reproducer
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
mkdir lower upper work merge
|
|
David Disseldorp |
14422d |
touch lower/old
|
|
David Disseldorp |
14422d |
touch lower/new
|
|
David Disseldorp |
14422d |
mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merge
|
|
David Disseldorp |
14422d |
rm merge/new
|
|
David Disseldorp |
14422d |
mv merge/old merge/new & unlink upper/new
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
may result in this race:
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
PROCESS A:
|
|
David Disseldorp |
14422d |
rename("merge/old", "merge/new");
|
|
David Disseldorp |
14422d |
overwrite=true,ovl_lower_positive(old)=true,
|
|
David Disseldorp |
14422d |
ovl_dentry_is_whiteout(new)=true -> flags |= RENAME_EXCHANGE
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
PROCESS B:
|
|
David Disseldorp |
14422d |
unlink("upper/new");
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
PROCESS A:
|
|
David Disseldorp |
14422d |
lookup newdentry in new_upperdir
|
|
David Disseldorp |
14422d |
call vfs_rename() with negative newdentry and RENAME_EXCHANGE
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
Fix by adding the missing check for negative newdentry.
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
Signed-off-by: Zheng Liang <zhengliang6@huawei.com>
|
|
David Disseldorp |
14422d |
Fixes: e9be9d5e76e3 ("overlay filesystem")
|
|
David Disseldorp |
14422d |
Cc: <stable@vger.kernel.org> # v3.18
|
|
David Disseldorp |
14422d |
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
|
|
David Disseldorp |
14422d |
Acked-by: David Disseldorp <ddiss@suse.de>
|
|
David Disseldorp |
14422d |
---
|
|
David Disseldorp |
14422d |
fs/overlayfs/dir.c | 10 +++++++---
|
|
David Disseldorp |
14422d |
1 file changed, 7 insertions(+), 3 deletions(-)
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
|
|
David Disseldorp |
14422d |
index 6509ec3cb373..3284363ebdfb 100644
|
|
David Disseldorp |
14422d |
--- a/fs/overlayfs/dir.c
|
|
David Disseldorp |
14422d |
+++ b/fs/overlayfs/dir.c
|
|
David Disseldorp |
14422d |
@@ -1160,9 +1160,13 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
|
|
David Disseldorp |
14422d |
goto out_dput;
|
|
David Disseldorp |
14422d |
}
|
|
David Disseldorp |
14422d |
} else {
|
|
David Disseldorp |
14422d |
- if (!d_is_negative(newdentry) &&
|
|
David Disseldorp |
14422d |
- (!new_opaque || !ovl_is_whiteout(newdentry)))
|
|
David Disseldorp |
14422d |
- goto out_dput;
|
|
David Disseldorp |
14422d |
+ if (!d_is_negative(newdentry)) {
|
|
David Disseldorp |
14422d |
+ if (!new_opaque || !ovl_is_whiteout(newdentry))
|
|
David Disseldorp |
14422d |
+ goto out_dput;
|
|
David Disseldorp |
14422d |
+ } else {
|
|
David Disseldorp |
14422d |
+ if (flags & RENAME_EXCHANGE)
|
|
David Disseldorp |
14422d |
+ goto out_dput;
|
|
David Disseldorp |
14422d |
+ }
|
|
David Disseldorp |
14422d |
}
|
|
David Disseldorp |
14422d |
|
|
David Disseldorp |
14422d |
if (olddentry == trap)
|
|
David Disseldorp |
14422d |
--
|
|
David Disseldorp |
14422d |
2.34.1
|
|
David Disseldorp |
14422d |
|