diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-01 17:08:43 +0200 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-01 17:08:43 +0200 |
commit | da1ce0670c14d8380e423a3239e562a1dc15fa9e (patch) | |
tree | 146ea4ac0fbf5550db8e65a59ddc7c668b68db76 /security/security.c | |
parent | 4fd699ae3fbca2ac760137e1d26f98a105f59f05 (diff) | |
download | lwn-da1ce0670c14d8380e423a3239e562a1dc15fa9e.tar.gz lwn-da1ce0670c14d8380e423a3239e562a1dc15fa9e.zip |
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/security.c')
-rw-r--r-- | security/security.c | 16 |
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); } |