aboutsummaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorMiklos Szeredi2014-04-01 17:08:43 +0200
committerMiklos Szeredi2014-04-01 17:08:43 +0200
commitda1ce0670c14d8380e423a3239e562a1dc15fa9e (patch)
tree146ea4ac0fbf5550db8e65a59ddc7c668b68db76 /security
parent4fd699ae3fbca2ac760137e1d26f98a105f59f05 (diff)
vfs: add cross-rename
If flags contain RENAME_EXCHANGE then exchange source and destination files. There's no restriction on the type of the files; e.g. a directory can be exchanged with a symlink. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'security')
-rw-r--r--security/security.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/security/security.c b/security/security.c
index 284fbc99aa9d..8b774f362a3d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -439,6 +439,14 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
(new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
return 0;
+
+ if (flags & RENAME_EXCHANGE) {
+ int err = security_ops->path_rename(new_dir, new_dentry,
+ old_dir, old_dentry);
+ if (err)
+ return err;
+ }
+
return security_ops->path_rename(old_dir, old_dentry, new_dir,
new_dentry);
}
@@ -531,6 +539,14 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
(new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
return 0;
+
+ if (flags & RENAME_EXCHANGE) {
+ int err = security_ops->inode_rename(new_dir, new_dentry,
+ old_dir, old_dentry);
+ if (err)
+ return err;
+ }
+
return security_ops->inode_rename(old_dir, old_dentry,
new_dir, new_dentry);
}