.. | .. |
---|
| 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, |
---|