| .. | .. | 
|---|
 | 1 | +// SPDX-License-Identifier: GPL-2.0-or-later  | 
|---|
| 1 | 2 |  /** | 
|---|
| 2 | 3 |   * eCryptfs: Linux filesystem encryption layer | 
|---|
| 3 | 4 |   * | 
|---|
| .. | .. | 
|---|
| 6 | 7 |   * Copyright (C) 2004-2007 International Business Machines Corp. | 
|---|
| 7 | 8 |   *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 
|---|
| 8 | 9 |   *              Michael C. Thompsion <mcthomps@us.ibm.com> | 
|---|
| 9 |  | - *  | 
|---|
| 10 |  | - * This program is free software; you can redistribute it and/or  | 
|---|
| 11 |  | - * modify it under the terms of the GNU General Public License as  | 
|---|
| 12 |  | - * published by the Free Software Foundation; either version 2 of the  | 
|---|
| 13 |  | - * License, or (at your option) any later version.  | 
|---|
| 14 |  | - *  | 
|---|
| 15 |  | - * This program is distributed in the hope that it will be useful, but  | 
|---|
| 16 |  | - * WITHOUT ANY WARRANTY; without even the implied warranty of  | 
|---|
| 17 |  | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  | 
|---|
| 18 |  | - * General Public License for more details.  | 
|---|
| 19 |  | - *  | 
|---|
| 20 |  | - * You should have received a copy of the GNU General Public License  | 
|---|
| 21 |  | - * along with this program; if not, write to the Free Software  | 
|---|
| 22 |  | - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  | 
|---|
| 23 |  | - * 02111-1307, USA.  | 
|---|
| 24 | 10 |   */ | 
|---|
| 25 | 11 |   | 
|---|
| 26 | 12 |  #include <linux/file.h> | 
|---|
| .. | .. | 
|---|
| 142 | 128 |  			      struct inode *inode) | 
|---|
| 143 | 129 |  { | 
|---|
| 144 | 130 |  	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); | 
|---|
| 145 |  | -	struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);  | 
|---|
| 146 | 131 |  	struct dentry *lower_dir_dentry; | 
|---|
 | 132 | +	struct inode *lower_dir_inode;  | 
|---|
| 147 | 133 |  	int rc; | 
|---|
| 148 | 134 |   | 
|---|
| 149 |  | -	dget(lower_dentry);  | 
|---|
| 150 |  | -	lower_dir_dentry = lock_parent(lower_dentry);  | 
|---|
| 151 |  | -	rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL);  | 
|---|
 | 135 | +	lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent);  | 
|---|
 | 136 | +	lower_dir_inode = d_inode(lower_dir_dentry);  | 
|---|
 | 137 | +	inode_lock_nested(lower_dir_inode, I_MUTEX_PARENT);  | 
|---|
 | 138 | +	dget(lower_dentry);	// don't even try to make the lower negative  | 
|---|
 | 139 | +	if (lower_dentry->d_parent != lower_dir_dentry)  | 
|---|
 | 140 | +		rc = -EINVAL;  | 
|---|
 | 141 | +	else if (d_unhashed(lower_dentry))  | 
|---|
 | 142 | +		rc = -EINVAL;  | 
|---|
 | 143 | +	else  | 
|---|
 | 144 | +		rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL);  | 
|---|
| 152 | 145 |  	if (rc) { | 
|---|
| 153 | 146 |  		printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); | 
|---|
| 154 | 147 |  		goto out_unlock; | 
|---|
| .. | .. | 
|---|
| 156 | 149 |  	fsstack_copy_attr_times(dir, lower_dir_inode); | 
|---|
| 157 | 150 |  	set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink); | 
|---|
| 158 | 151 |  	inode->i_ctime = dir->i_ctime; | 
|---|
| 159 |  | -	d_drop(dentry);  | 
|---|
| 160 | 152 |  out_unlock: | 
|---|
| 161 |  | -	unlock_dir(lower_dir_dentry);  | 
|---|
| 162 | 153 |  	dput(lower_dentry); | 
|---|
 | 154 | +	inode_unlock(lower_dir_inode);  | 
|---|
 | 155 | +	if (!rc)  | 
|---|
 | 156 | +		d_drop(dentry);  | 
|---|
| 163 | 157 |  	return rc; | 
|---|
| 164 | 158 |  } | 
|---|
| 165 | 159 |   | 
|---|
| .. | .. | 
|---|
| 533 | 527 |  { | 
|---|
| 534 | 528 |  	struct dentry *lower_dentry; | 
|---|
| 535 | 529 |  	struct dentry *lower_dir_dentry; | 
|---|
 | 530 | +	struct inode *lower_dir_inode;  | 
|---|
| 536 | 531 |  	int rc; | 
|---|
| 537 | 532 |   | 
|---|
| 538 | 533 |  	lower_dentry = ecryptfs_dentry_to_lower(dentry); | 
|---|
| 539 |  | -	dget(dentry);  | 
|---|
| 540 |  | -	lower_dir_dentry = lock_parent(lower_dentry);  | 
|---|
| 541 |  | -	dget(lower_dentry);  | 
|---|
| 542 |  | -	rc = vfs_rmdir(d_inode(lower_dir_dentry), lower_dentry);  | 
|---|
| 543 |  | -	dput(lower_dentry);  | 
|---|
| 544 |  | -	if (!rc && d_really_is_positive(dentry))  | 
|---|
 | 534 | +	lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent);  | 
|---|
 | 535 | +	lower_dir_inode = d_inode(lower_dir_dentry);  | 
|---|
 | 536 | +  | 
|---|
 | 537 | +	inode_lock_nested(lower_dir_inode, I_MUTEX_PARENT);  | 
|---|
 | 538 | +	dget(lower_dentry);	// don't even try to make the lower negative  | 
|---|
 | 539 | +	if (lower_dentry->d_parent != lower_dir_dentry)  | 
|---|
 | 540 | +		rc = -EINVAL;  | 
|---|
 | 541 | +	else if (d_unhashed(lower_dentry))  | 
|---|
 | 542 | +		rc = -EINVAL;  | 
|---|
 | 543 | +	else  | 
|---|
 | 544 | +		rc = vfs_rmdir(lower_dir_inode, lower_dentry);  | 
|---|
 | 545 | +	if (!rc) {  | 
|---|
| 545 | 546 |  		clear_nlink(d_inode(dentry)); | 
|---|
| 546 |  | -	fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));  | 
|---|
| 547 |  | -	set_nlink(dir, d_inode(lower_dir_dentry)->i_nlink);  | 
|---|
| 548 |  | -	unlock_dir(lower_dir_dentry);  | 
|---|
 | 547 | +		fsstack_copy_attr_times(dir, lower_dir_inode);  | 
|---|
 | 548 | +		set_nlink(dir, lower_dir_inode->i_nlink);  | 
|---|
 | 549 | +	}  | 
|---|
 | 550 | +	dput(lower_dentry);  | 
|---|
 | 551 | +	inode_unlock(lower_dir_inode);  | 
|---|
| 549 | 552 |  	if (!rc) | 
|---|
| 550 | 553 |  		d_drop(dentry); | 
|---|
| 551 |  | -	dput(dentry);  | 
|---|
| 552 | 554 |  	return rc; | 
|---|
| 553 | 555 |  } | 
|---|
| 554 | 556 |   | 
|---|
| .. | .. | 
|---|
| 586 | 588 |  	struct dentry *lower_new_dentry; | 
|---|
| 587 | 589 |  	struct dentry *lower_old_dir_dentry; | 
|---|
| 588 | 590 |  	struct dentry *lower_new_dir_dentry; | 
|---|
| 589 |  | -	struct dentry *trap = NULL;  | 
|---|
 | 591 | +	struct dentry *trap;  | 
|---|
| 590 | 592 |  	struct inode *target_inode; | 
|---|
| 591 | 593 |   | 
|---|
| 592 | 594 |  	if (flags) | 
|---|
| 593 | 595 |  		return -EINVAL; | 
|---|
| 594 | 596 |   | 
|---|
 | 597 | +	lower_old_dir_dentry = ecryptfs_dentry_to_lower(old_dentry->d_parent);  | 
|---|
 | 598 | +	lower_new_dir_dentry = ecryptfs_dentry_to_lower(new_dentry->d_parent);  | 
|---|
 | 599 | +  | 
|---|
| 595 | 600 |  	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); | 
|---|
| 596 | 601 |  	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); | 
|---|
| 597 |  | -	dget(lower_old_dentry);  | 
|---|
| 598 |  | -	dget(lower_new_dentry);  | 
|---|
| 599 |  | -	lower_old_dir_dentry = dget_parent(lower_old_dentry);  | 
|---|
| 600 |  | -	lower_new_dir_dentry = dget_parent(lower_new_dentry);  | 
|---|
 | 602 | +  | 
|---|
| 601 | 603 |  	target_inode = d_inode(new_dentry); | 
|---|
 | 604 | +  | 
|---|
| 602 | 605 |  	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); | 
|---|
| 603 |  | -	/* source should not be ancestor of target */  | 
|---|
| 604 |  | -	if (trap == lower_old_dentry) {  | 
|---|
| 605 |  | -		rc = -EINVAL;  | 
|---|
 | 606 | +	dget(lower_new_dentry);  | 
|---|
 | 607 | +	rc = -EINVAL;  | 
|---|
 | 608 | +	if (lower_old_dentry->d_parent != lower_old_dir_dentry)  | 
|---|
| 606 | 609 |  		goto out_lock; | 
|---|
| 607 |  | -	}  | 
|---|
 | 610 | +	if (lower_new_dentry->d_parent != lower_new_dir_dentry)  | 
|---|
 | 611 | +		goto out_lock;  | 
|---|
 | 612 | +	if (d_unhashed(lower_old_dentry) || d_unhashed(lower_new_dentry))  | 
|---|
 | 613 | +		goto out_lock;  | 
|---|
 | 614 | +	/* source should not be ancestor of target */  | 
|---|
 | 615 | +	if (trap == lower_old_dentry)  | 
|---|
 | 616 | +		goto out_lock;  | 
|---|
| 608 | 617 |  	/* target should not be ancestor of source */ | 
|---|
| 609 | 618 |  	if (trap == lower_new_dentry) { | 
|---|
| 610 | 619 |  		rc = -ENOTEMPTY; | 
|---|
| .. | .. | 
|---|
| 622 | 631 |  	if (new_dir != old_dir) | 
|---|
| 623 | 632 |  		fsstack_copy_attr_all(old_dir, d_inode(lower_old_dir_dentry)); | 
|---|
| 624 | 633 |  out_lock: | 
|---|
| 625 |  | -	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);  | 
|---|
| 626 |  | -	dput(lower_new_dir_dentry);  | 
|---|
| 627 |  | -	dput(lower_old_dir_dentry);  | 
|---|
| 628 | 634 |  	dput(lower_new_dentry); | 
|---|
| 629 |  | -	dput(lower_old_dentry);  | 
|---|
 | 635 | +	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);  | 
|---|
| 630 | 636 |  	return rc; | 
|---|
| 631 | 637 |  } | 
|---|
| 632 | 638 |   | 
|---|
| .. | .. | 
|---|
| 1034 | 1040 |  		goto out; | 
|---|
| 1035 | 1041 |  	} | 
|---|
| 1036 | 1042 |  	inode_lock(lower_inode); | 
|---|
| 1037 |  | -	rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);  | 
|---|
 | 1043 | +	rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size,  | 
|---|
 | 1044 | +			    XATTR_NOSECURITY);  | 
|---|
| 1038 | 1045 |  	inode_unlock(lower_inode); | 
|---|
| 1039 | 1046 |  out: | 
|---|
| 1040 | 1047 |  	return rc; | 
|---|
| .. | .. | 
|---|
| 1119 | 1126 |   | 
|---|
| 1120 | 1127 |  static int ecryptfs_xattr_get(const struct xattr_handler *handler, | 
|---|
| 1121 | 1128 |  			      struct dentry *dentry, struct inode *inode, | 
|---|
| 1122 |  | -			      const char *name, void *buffer, size_t size)  | 
|---|
 | 1129 | +			      const char *name, void *buffer, size_t size,  | 
|---|
 | 1130 | +			      int flags)  | 
|---|
| 1123 | 1131 |  { | 
|---|
| 1124 | 1132 |  	return ecryptfs_getxattr(dentry, inode, name, buffer, size); | 
|---|
| 1125 | 1133 |  } | 
|---|
| .. | .. | 
|---|
| 1137 | 1145 |  	} | 
|---|
| 1138 | 1146 |  } | 
|---|
| 1139 | 1147 |   | 
|---|
| 1140 |  | -const struct xattr_handler ecryptfs_xattr_handler = {  | 
|---|
 | 1148 | +static const struct xattr_handler ecryptfs_xattr_handler = {  | 
|---|
| 1141 | 1149 |  	.prefix = "",  /* match anything */ | 
|---|
| 1142 | 1150 |  	.get = ecryptfs_xattr_get, | 
|---|
| 1143 | 1151 |  	.set = ecryptfs_xattr_set, | 
|---|