summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhang Xiaoxu <zhangxiaoxu5@huawei.com>2020-06-28 21:06:38 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-07-09 09:35:09 +0200
commit3fe62ca7096cd9ae74b07282e79b9568d4a129a3 (patch)
tree0f83dcc1f0dfe45fe6101e61a054b9ff580a95e1
parent45999d78c5051cee0399fec398d6e1b7b26a8a60 (diff)
downloadlinux-stable-3fe62ca7096cd9ae74b07282e79b9568d4a129a3.tar.gz
linux-stable-3fe62ca7096cd9ae74b07282e79b9568d4a129a3.tar.bz2
linux-stable-3fe62ca7096cd9ae74b07282e79b9568d4a129a3.zip
cifs: Fix the target file was deleted when rename failed.
commit 9ffad9263b467efd8f8dc7ae1941a0a655a2bab2 upstream. When xfstest generic/035, we found the target file was deleted if the rename return -EACESS. In cifs_rename2, we unlink the positive target dentry if rename failed with EACESS or EEXIST, even if the target dentry is positived before rename. Then the existing file was deleted. We should just delete the target file which created during the rename. Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com> Cc: stable@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com> Reviewed-by: Aurelien Aptel <aaptel@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/cifs/inode.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index c18c26a78453..a002e289a544 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1737,6 +1737,7 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
FILE_UNIX_BASIC_INFO *info_buf_target;
unsigned int xid;
int rc, tmprc;
+ bool new_target = d_really_is_negative(target_dentry);
if (flags & ~RENAME_NOREPLACE)
return -EINVAL;
@@ -1813,8 +1814,13 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
*/
unlink_target:
- /* Try unlinking the target dentry if it's not negative */
- if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
+ /*
+ * If the target dentry was created during the rename, try
+ * unlinking it if it's not negative
+ */
+ if (new_target &&
+ d_really_is_positive(target_dentry) &&
+ (rc == -EACCES || rc == -EEXIST)) {
if (d_is_dir(target_dentry))
tmprc = cifs_rmdir(target_dir, target_dentry);
else