aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dcache.c50
-rw-r--r--fs/namei.c104
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/uapi/linux/fs.h1
-rw-r--r--security/security.c16
5 files changed, 131 insertions, 41 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index ca02c13a84aa..66cba5a8a346 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2483,12 +2483,14 @@ static void switch_names(struct dentry *dentry, struct dentry *target)
2483 dentry->d_name.name = dentry->d_iname; 2483 dentry->d_name.name = dentry->d_iname;
2484 } else { 2484 } else {
2485 /* 2485 /*
2486 * Both are internal. Just copy target to dentry 2486 * Both are internal.
2487 */ 2487 */
2488 memcpy(dentry->d_iname, target->d_name.name, 2488 unsigned int i;
2489 target->d_name.len + 1); 2489 BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long)));
2490 dentry->d_name.len = target->d_name.len; 2490 for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) {
2491 return; 2491 swap(((long *) &dentry->d_iname)[i],
2492 ((long *) &target->d_iname)[i]);
2493 }
2492 } 2494 }
2493 } 2495 }
2494 swap(dentry->d_name.len, target->d_name.len); 2496 swap(dentry->d_name.len, target->d_name.len);
@@ -2545,13 +2547,15 @@ static void dentry_unlock_parents_for_move(struct dentry *dentry,
2545 * __d_move - move a dentry 2547 * __d_move - move a dentry
2546 * @dentry: entry to move 2548 * @dentry: entry to move
2547 * @target: new dentry 2549 * @target: new dentry
2550 * @exchange: exchange the two dentries
2548 * 2551 *
2549 * Update the dcache to reflect the move of a file name. Negative 2552 * Update the dcache to reflect the move of a file name. Negative
2550 * dcache entries should not be moved in this way. Caller must hold 2553 * dcache entries should not be moved in this way. Caller must hold
2551 * rename_lock, the i_mutex of the source and target directories, 2554 * rename_lock, the i_mutex of the source and target directories,
2552 * and the sb->s_vfs_rename_mutex if they differ. See lock_rename(). 2555 * and the sb->s_vfs_rename_mutex if they differ. See lock_rename().
2553 */ 2556 */
2554static void __d_move(struct dentry * dentry, struct dentry * target) 2557static void __d_move(struct dentry *dentry, struct dentry *target,
2558 bool exchange)
2555{ 2559{
2556 if (!dentry->d_inode) 2560 if (!dentry->d_inode)
2557 printk(KERN_WARNING "VFS: moving negative dcache entry\n"); 2561 printk(KERN_WARNING "VFS: moving negative dcache entry\n");
@@ -2573,8 +2577,15 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
2573 __d_drop(dentry); 2577 __d_drop(dentry);
2574 __d_rehash(dentry, d_hash(target->d_parent, target->d_name.hash)); 2578 __d_rehash(dentry, d_hash(target->d_parent, target->d_name.hash));
2575 2579
2576 /* Unhash the target: dput() will then get rid of it */ 2580 /*
2581 * Unhash the target (d_delete() is not usable here). If exchanging
2582 * the two dentries, then rehash onto the other's hash queue.
2583 */
2577 __d_drop(target); 2584 __d_drop(target);
2585 if (exchange) {
2586 __d_rehash(target,
2587 d_hash(dentry->d_parent, dentry->d_name.hash));
2588 }
2578 2589
2579 list_del(&dentry->d_u.d_child); 2590 list_del(&dentry->d_u.d_child);
2580 list_del(&target->d_u.d_child); 2591 list_del(&target->d_u.d_child);
@@ -2601,6 +2612,8 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
2601 write_seqcount_end(&dentry->d_seq); 2612 write_seqcount_end(&dentry->d_seq);
2602 2613
2603 dentry_unlock_parents_for_move(dentry, target); 2614 dentry_unlock_parents_for_move(dentry, target);
2615 if (exchange)
2616 fsnotify_d_move(target);
2604 spin_unlock(&target->d_lock); 2617 spin_unlock(&target->d_lock);
2605 fsnotify_d_move(dentry); 2618 fsnotify_d_move(dentry);
2606 spin_unlock(&dentry->d_lock); 2619 spin_unlock(&dentry->d_lock);
@@ -2618,11 +2631,30 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
2618void d_move(struct dentry *dentry, struct dentry *target) 2631void d_move(struct dentry *dentry, struct dentry *target)
2619{ 2632{
2620 write_seqlock(&rename_lock); 2633 write_seqlock(&rename_lock);
2621 __d_move(dentry, target); 2634 __d_move(dentry, target, false);
2622 write_sequnlock(&rename_lock); 2635 write_sequnlock(&rename_lock);
2623} 2636}
2624EXPORT_SYMBOL(d_move); 2637EXPORT_SYMBOL(d_move);
2625 2638
2639/*
2640 * d_exchange - exchange two dentries
2641 * @dentry1: first dentry
2642 * @dentry2: second dentry
2643 */
2644void d_exchange(struct dentry *dentry1, struct dentry *dentry2)
2645{
2646 write_seqlock(&rename_lock);
2647
2648 WARN_ON(!dentry1->d_inode);
2649 WARN_ON(!dentry2->d_inode);
2650 WARN_ON(IS_ROOT(dentry1));
2651 WARN_ON(IS_ROOT(dentry2));
2652
2653 __d_move(dentry1, dentry2, true);
2654
2655 write_sequnlock(&rename_lock);
2656}
2657
2626/** 2658/**
2627 * d_ancestor - search for an ancestor 2659 * d_ancestor - search for an ancestor
2628 * @p1: ancestor dentry 2660 * @p1: ancestor dentry
@@ -2670,7 +2702,7 @@ static struct dentry *__d_unalias(struct inode *inode,
2670 m2 = &alias->d_parent->d_inode->i_mutex; 2702 m2 = &alias->d_parent->d_inode->i_mutex;
2671out_unalias: 2703out_unalias:
2672 if (likely(!d_mountpoint(alias))) { 2704 if (likely(!d_mountpoint(alias))) {
2673 __d_move(alias, dentry); 2705 __d_move(alias, dentry, false);
2674 ret = alias; 2706 ret = alias;
2675 } 2707 }
2676out_err: 2708out_err:
diff --git a/fs/namei.c b/fs/namei.c
index 4096d589bb3f..c1178880f23c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4031,6 +4031,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
4031 const unsigned char *old_name; 4031 const unsigned char *old_name;
4032 struct inode *source = old_dentry->d_inode; 4032 struct inode *source = old_dentry->d_inode;
4033 struct inode *target = new_dentry->d_inode; 4033 struct inode *target = new_dentry->d_inode;
4034 bool new_is_dir = false;
4035 unsigned max_links = new_dir->i_sb->s_max_links;
4034 4036
4035 if (source == target) 4037 if (source == target)
4036 return 0; 4038 return 0;
@@ -4039,10 +4041,16 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
4039 if (error) 4041 if (error)
4040 return error; 4042 return error;
4041 4043
4042 if (!target) 4044 if (!target) {
4043 error = may_create(new_dir, new_dentry); 4045 error = may_create(new_dir, new_dentry);
4044 else 4046 } else {
4045 error = may_delete(new_dir, new_dentry, is_dir); 4047 new_is_dir = d_is_dir(new_dentry);
4048
4049 if (!(flags & RENAME_EXCHANGE))
4050 error = may_delete(new_dir, new_dentry, is_dir);
4051 else
4052 error = may_delete(new_dir, new_dentry, new_is_dir);
4053 }
4046 if (error) 4054 if (error)
4047 return error; 4055 return error;
4048 4056
@@ -4056,10 +4064,17 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
4056 * If we are going to change the parent - check write permissions, 4064 * If we are going to change the parent - check write permissions,
4057 * we'll need to flip '..'. 4065 * we'll need to flip '..'.
4058 */ 4066 */
4059 if (is_dir && new_dir != old_dir) { 4067 if (new_dir != old_dir) {
4060 error = inode_permission(source, MAY_WRITE); 4068 if (is_dir) {
4061 if (error) 4069 error = inode_permission(source, MAY_WRITE);
4062 return error; 4070 if (error)
4071 return error;
4072 }
4073 if ((flags & RENAME_EXCHANGE) && new_is_dir) {
4074 error = inode_permission(target, MAY_WRITE);
4075 if (error)
4076 return error;
4077 }
4063 } 4078 }
4064 4079
4065 error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry, 4080 error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry,
@@ -4069,7 +4084,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
4069 4084
4070 old_name = fsnotify_oldname_init(old_dentry->d_name.name); 4085 old_name = fsnotify_oldname_init(old_dentry->d_name.name);
4071 dget(new_dentry); 4086 dget(new_dentry);
4072 if (!is_dir) 4087 if (!is_dir || (flags & RENAME_EXCHANGE))
4073 lock_two_nondirectories(source, target); 4088 lock_two_nondirectories(source, target);
4074 else if (target) 4089 else if (target)
4075 mutex_lock(&target->i_mutex); 4090 mutex_lock(&target->i_mutex);
@@ -4078,25 +4093,25 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
4078 if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry)) 4093 if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry))
4079 goto out; 4094 goto out;
4080 4095
4081 if (is_dir) { 4096 if (max_links && new_dir != old_dir) {
4082 unsigned max_links = new_dir->i_sb->s_max_links;
4083
4084 error = -EMLINK; 4097 error = -EMLINK;
4085 if (max_links && !target && new_dir != old_dir && 4098 if (is_dir && !new_is_dir && new_dir->i_nlink >= max_links)
4086 new_dir->i_nlink >= max_links)
4087 goto out; 4099 goto out;
4088 4100 if ((flags & RENAME_EXCHANGE) && !is_dir && new_is_dir &&
4089 if (target) 4101 old_dir->i_nlink >= max_links)
4090 shrink_dcache_parent(new_dentry); 4102 goto out;
4091 } else { 4103 }
4104 if (is_dir && !(flags & RENAME_EXCHANGE) && target)
4105 shrink_dcache_parent(new_dentry);
4106 if (!is_dir) {
4092 error = try_break_deleg(source, delegated_inode); 4107 error = try_break_deleg(source, delegated_inode);
4093 if (error) 4108 if (error)
4094 goto out; 4109 goto out;
4095 if (target) { 4110 }
4096 error = try_break_deleg(target, delegated_inode); 4111 if (target && !new_is_dir) {
4097 if (error) 4112 error = try_break_deleg(target, delegated_inode);
4098 goto out; 4113 if (error)
4099 } 4114 goto out;
4100 } 4115 }
4101 if (!flags) { 4116 if (!flags) {
4102 error = old_dir->i_op->rename(old_dir, old_dentry, 4117 error = old_dir->i_op->rename(old_dir, old_dentry,
@@ -4108,22 +4123,31 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
4108 if (error) 4123 if (error)
4109 goto out; 4124 goto out;
4110 4125
4111 if (target) { 4126 if (!(flags & RENAME_EXCHANGE) && target) {
4112 if (is_dir) 4127 if (is_dir)
4113 target->i_flags |= S_DEAD; 4128 target->i_flags |= S_DEAD;
4114 dont_mount(new_dentry); 4129 dont_mount(new_dentry);
4115 } 4130 }
4116 if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) 4131 if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) {
4117 d_move(old_dentry, new_dentry); 4132 if (!(flags & RENAME_EXCHANGE))
4133 d_move(old_dentry, new_dentry);
4134 else
4135 d_exchange(old_dentry, new_dentry);
4136 }
4118out: 4137out:
4119 if (!is_dir) 4138 if (!is_dir || (flags & RENAME_EXCHANGE))
4120 unlock_two_nondirectories(source, target); 4139 unlock_two_nondirectories(source, target);
4121 else if (target) 4140 else if (target)
4122 mutex_unlock(&target->i_mutex); 4141 mutex_unlock(&target->i_mutex);
4123 dput(new_dentry); 4142 dput(new_dentry);
4124 if (!error) 4143 if (!error) {
4125 fsnotify_move(old_dir, new_dir, old_name, is_dir, 4144 fsnotify_move(old_dir, new_dir, old_name, is_dir,
4126 target, old_dentry); 4145 !(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry);
4146 if (flags & RENAME_EXCHANGE) {
4147 fsnotify_move(new_dir, old_dir, old_dentry->d_name.name,
4148 new_is_dir, NULL, new_dentry);
4149 }
4150 }
4127 fsnotify_oldname_free(old_name); 4151 fsnotify_oldname_free(old_name);
4128 4152
4129 return error; 4153 return error;
@@ -4143,7 +4167,10 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
4143 bool should_retry = false; 4167 bool should_retry = false;
4144 int error; 4168 int error;
4145 4169
4146 if (flags & ~RENAME_NOREPLACE) 4170 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
4171 return -EINVAL;
4172
4173 if ((flags & RENAME_NOREPLACE) && (flags & RENAME_EXCHANGE))
4147 return -EINVAL; 4174 return -EINVAL;
4148 4175
4149retry: 4176retry:
@@ -4180,7 +4207,8 @@ retry:
4180 4207
4181 oldnd.flags &= ~LOOKUP_PARENT; 4208 oldnd.flags &= ~LOOKUP_PARENT;
4182 newnd.flags &= ~LOOKUP_PARENT; 4209 newnd.flags &= ~LOOKUP_PARENT;
4183 newnd.flags |= LOOKUP_RENAME_TARGET; 4210 if (!(flags & RENAME_EXCHANGE))
4211 newnd.flags |= LOOKUP_RENAME_TARGET;
4184 4212
4185retry_deleg: 4213retry_deleg:
4186 trap = lock_rename(new_dir, old_dir); 4214 trap = lock_rename(new_dir, old_dir);
@@ -4200,12 +4228,23 @@ retry_deleg:
4200 error = -EEXIST; 4228 error = -EEXIST;
4201 if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) 4229 if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry))
4202 goto exit5; 4230 goto exit5;
4231 if (flags & RENAME_EXCHANGE) {
4232 error = -ENOENT;
4233 if (d_is_negative(new_dentry))
4234 goto exit5;
4235
4236 if (!d_is_dir(new_dentry)) {
4237 error = -ENOTDIR;
4238 if (newnd.last.name[newnd.last.len])
4239 goto exit5;
4240 }
4241 }
4203 /* unless the source is a directory trailing slashes give -ENOTDIR */ 4242 /* unless the source is a directory trailing slashes give -ENOTDIR */
4204 if (!d_is_dir(old_dentry)) { 4243 if (!d_is_dir(old_dentry)) {
4205 error = -ENOTDIR; 4244 error = -ENOTDIR;
4206 if (oldnd.last.name[oldnd.last.len]) 4245 if (oldnd.last.name[oldnd.last.len])
4207 goto exit5; 4246 goto exit5;
4208 if (newnd.last.name[newnd.last.len]) 4247 if (!(flags & RENAME_EXCHANGE) && newnd.last.name[newnd.last.len])
4209 goto exit5; 4248 goto exit5;
4210 } 4249 }
4211 /* source should not be ancestor of target */ 4250 /* source should not be ancestor of target */
@@ -4213,7 +4252,8 @@ retry_deleg:
4213 if (old_dentry == trap) 4252 if (old_dentry == trap)
4214 goto exit5; 4253 goto exit5;
4215 /* target should not be an ancestor of source */ 4254 /* target should not be an ancestor of source */
4216 error = -ENOTEMPTY; 4255 if (!(flags & RENAME_EXCHANGE))
4256 error = -ENOTEMPTY;
4217 if (new_dentry == trap) 4257 if (new_dentry == trap)
4218 goto exit5; 4258 goto exit5;
4219 4259
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 3b50cac7ccb3..3b9bfdb83ba6 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -308,6 +308,7 @@ extern void dentry_update_name_case(struct dentry *, struct qstr *);
308 308
309/* used for rename() and baskets */ 309/* used for rename() and baskets */
310extern void d_move(struct dentry *, struct dentry *); 310extern void d_move(struct dentry *, struct dentry *);
311extern void d_exchange(struct dentry *, struct dentry *);
311extern struct dentry *d_ancestor(struct dentry *, struct dentry *); 312extern struct dentry *d_ancestor(struct dentry *, struct dentry *);
312 313
313/* appendix may either be NULL or be used for transname suffixes */ 314/* appendix may either be NULL or be used for transname suffixes */
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 9250f4dd7d96..ca1a11bb4443 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -36,6 +36,7 @@
36#define SEEK_MAX SEEK_HOLE 36#define SEEK_MAX SEEK_HOLE
37 37
38#define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */ 38#define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */
39#define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */
39 40
40struct fstrim_range { 41struct fstrim_range {
41 __u64 start; 42 __u64 start;
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,
439 if (unlikely(IS_PRIVATE(old_dentry->d_inode) || 439 if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
440 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) 440 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
441 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
442 return security_ops->path_rename(old_dir, old_dentry, new_dir, 450 return security_ops->path_rename(old_dir, old_dentry, new_dir,
443 new_dentry); 451 new_dentry);
444} 452}
@@ -531,6 +539,14 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
531 if (unlikely(IS_PRIVATE(old_dentry->d_inode) || 539 if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
532 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) 540 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
533 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
534 return security_ops->inode_rename(old_dir, old_dentry, 550 return security_ops->inode_rename(old_dir, old_dentry,
535 new_dir, new_dentry); 551 new_dir, new_dentry);
536} 552}