aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-04 17:03:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-04 17:03:05 -0400
commit7df934526c0b3775613502dcd19ab6d2da8cce1e (patch)
tree01e6a4ea20c676228f4acefc6ae776d2e52072db /security
parent3c83e61e67256e0bb08c46cc2db43b58fd617251 (diff)
parentbd42998a6bcb9b1708dac9ca9876e3d304c16f3d (diff)
Merge branch 'cross-rename' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull renameat2 system call from Miklos Szeredi: "This adds a new syscall, renameat2(), which is the same as renameat() but with a flags argument. The purpose of extending rename is to add cross-rename, a symmetric variant of rename, which exchanges the two files. This allows interesting things, which were not possible before, for example atomically replacing a directory tree with a symlink, etc... This also allows overlayfs and friends to operate on whiteouts atomically. Andy Lutomirski also suggested a "noreplace" flag, which disables the overwriting behavior of rename. These two flags, RENAME_EXCHANGE and RENAME_NOREPLACE are only implemented for ext4 as an example and for testing" * 'cross-rename' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ext4: add cross rename support ext4: rename: split out helper functions ext4: rename: move EMLINK check up ext4: rename: create ext4_renament structure for local vars vfs: add cross-rename vfs: lock_two_nondirectories: allow directory args security: add flags to rename hooks vfs: add RENAME_NOREPLACE flag vfs: add renameat2 syscall vfs: rename: use common code for dir and non-dir vfs: rename: move d_move() up vfs: add d_is_dir()
Diffstat (limited to 'security')
-rw-r--r--security/security.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/security/security.c b/security/security.c
index 919cad93ac82..8b774f362a3d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -433,11 +433,20 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
433} 433}
434 434
435int security_path_rename(struct path *old_dir, struct dentry *old_dentry, 435int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
436 struct path *new_dir, struct dentry *new_dentry) 436 struct path *new_dir, struct dentry *new_dentry,
437 unsigned int flags)
437{ 438{
438 if (unlikely(IS_PRIVATE(old_dentry->d_inode) || 439 if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
439 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) 440 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
440 return 0; 441 return 0;
442
443 if (flags & RENAME_EXCHANGE) {
444 int err = security_ops->path_rename(new_dir, new_dentry,
445 old_dir, old_dentry);
446 if (err)
447 return err;
448 }
449
441 return security_ops->path_rename(old_dir, old_dentry, new_dir, 450 return security_ops->path_rename(old_dir, old_dentry, new_dir,
442 new_dentry); 451 new_dentry);
443} 452}
@@ -524,11 +533,20 @@ int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
524} 533}
525 534
526int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, 535int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
527 struct inode *new_dir, struct dentry *new_dentry) 536 struct inode *new_dir, struct dentry *new_dentry,
537 unsigned int flags)
528{ 538{
529 if (unlikely(IS_PRIVATE(old_dentry->d_inode) || 539 if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
530 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) 540 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
531 return 0; 541 return 0;
542
543 if (flags & RENAME_EXCHANGE) {
544 int err = security_ops->inode_rename(new_dir, new_dentry,
545 old_dir, old_dentry);
546 if (err)
547 return err;
548 }
549
532 return security_ops->inode_rename(old_dir, old_dentry, 550 return security_ops->inode_rename(old_dir, old_dentry,
533 new_dir, new_dentry); 551 new_dir, new_dentry);
534} 552}