.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* * This file is part of UBIFS. |
---|
2 | 3 | * |
---|
3 | 4 | * Copyright (C) 2006-2008 Nokia Corporation. |
---|
4 | 5 | * Copyright (C) 2006, 2007 University of Szeged, Hungary |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it |
---|
7 | | - * under the terms of the GNU General Public License version 2 as published by |
---|
8 | | - * the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
13 | | - * more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License along with |
---|
16 | | - * this program; if not, write to the Free Software Foundation, Inc., 51 |
---|
17 | | - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
---|
18 | 6 | * |
---|
19 | 7 | * Authors: Artem Bityutskiy (Битюцкий Артём) |
---|
20 | 8 | * Adrian Hunter |
---|
.. | .. |
---|
93 | 81 | struct ubifs_inode *ui; |
---|
94 | 82 | bool encrypted = false; |
---|
95 | 83 | |
---|
96 | | - if (ubifs_crypt_is_encrypted(dir)) { |
---|
97 | | - err = fscrypt_get_encryption_info(dir); |
---|
98 | | - if (err) { |
---|
99 | | - ubifs_err(c, "fscrypt_get_encryption_info failed: %i", err); |
---|
100 | | - return ERR_PTR(err); |
---|
101 | | - } |
---|
102 | | - |
---|
103 | | - if (!fscrypt_has_encryption_key(dir)) |
---|
104 | | - return ERR_PTR(-EPERM); |
---|
105 | | - |
---|
106 | | - encrypted = true; |
---|
107 | | - } |
---|
108 | | - |
---|
109 | 84 | inode = new_inode(c->vfs_sb); |
---|
110 | 85 | ui = ubifs_inode(inode); |
---|
111 | 86 | if (!inode) |
---|
.. | .. |
---|
123 | 98 | inode->i_mtime = inode->i_atime = inode->i_ctime = |
---|
124 | 99 | current_time(inode); |
---|
125 | 100 | inode->i_mapping->nrpages = 0; |
---|
| 101 | + |
---|
| 102 | + err = fscrypt_prepare_new_inode(dir, inode, &encrypted); |
---|
| 103 | + if (err) { |
---|
| 104 | + ubifs_err(c, "fscrypt_prepare_new_inode failed: %i", err); |
---|
| 105 | + goto out_iput; |
---|
| 106 | + } |
---|
126 | 107 | |
---|
127 | 108 | switch (mode & S_IFMT) { |
---|
128 | 109 | case S_IFREG: |
---|
.. | .. |
---|
143 | 124 | case S_IFBLK: |
---|
144 | 125 | case S_IFCHR: |
---|
145 | 126 | inode->i_op = &ubifs_file_inode_operations; |
---|
146 | | - encrypted = false; |
---|
147 | 127 | break; |
---|
148 | 128 | default: |
---|
149 | 129 | BUG(); |
---|
.. | .. |
---|
163 | 143 | if (c->highest_inum >= INUM_WATERMARK) { |
---|
164 | 144 | spin_unlock(&c->cnt_lock); |
---|
165 | 145 | ubifs_err(c, "out of inode numbers"); |
---|
166 | | - make_bad_inode(inode); |
---|
167 | | - iput(inode); |
---|
168 | | - return ERR_PTR(-EINVAL); |
---|
| 146 | + err = -EINVAL; |
---|
| 147 | + goto out_iput; |
---|
169 | 148 | } |
---|
170 | 149 | ubifs_warn(c, "running out of inode numbers (current %lu, max %u)", |
---|
171 | 150 | (unsigned long)c->highest_inum, INUM_WATERMARK); |
---|
.. | .. |
---|
183 | 162 | spin_unlock(&c->cnt_lock); |
---|
184 | 163 | |
---|
185 | 164 | if (encrypted) { |
---|
186 | | - err = fscrypt_inherit_context(dir, inode, &encrypted, true); |
---|
| 165 | + err = fscrypt_set_context(inode, NULL); |
---|
187 | 166 | if (err) { |
---|
188 | | - ubifs_err(c, "fscrypt_inherit_context failed: %i", err); |
---|
189 | | - make_bad_inode(inode); |
---|
190 | | - iput(inode); |
---|
191 | | - return ERR_PTR(err); |
---|
| 167 | + ubifs_err(c, "fscrypt_set_context failed: %i", err); |
---|
| 168 | + goto out_iput; |
---|
192 | 169 | } |
---|
193 | 170 | } |
---|
194 | 171 | |
---|
195 | 172 | return inode; |
---|
| 173 | + |
---|
| 174 | +out_iput: |
---|
| 175 | + make_bad_inode(inode); |
---|
| 176 | + iput(inode); |
---|
| 177 | + return ERR_PTR(err); |
---|
196 | 178 | } |
---|
197 | 179 | |
---|
198 | 180 | static int dbg_check_name(const struct ubifs_info *c, |
---|
.. | .. |
---|
208 | 190 | return 0; |
---|
209 | 191 | } |
---|
210 | 192 | |
---|
211 | | -static void ubifs_set_d_ops(struct inode *dir, struct dentry *dentry); |
---|
212 | 193 | static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, |
---|
213 | 194 | unsigned int flags) |
---|
214 | 195 | { |
---|
.. | .. |
---|
222 | 203 | dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino); |
---|
223 | 204 | |
---|
224 | 205 | err = fscrypt_prepare_lookup(dir, dentry, &nm); |
---|
225 | | - ubifs_set_d_ops(dir, dentry); |
---|
| 206 | + generic_set_encrypted_ci_d_ops(dentry); |
---|
226 | 207 | if (err == -ENOENT) |
---|
227 | 208 | return d_splice_alias(NULL, dentry); |
---|
228 | 209 | if (err) |
---|
.. | .. |
---|
275 | 256 | goto done; |
---|
276 | 257 | } |
---|
277 | 258 | |
---|
278 | | - if (ubifs_crypt_is_encrypted(dir) && |
---|
| 259 | + if (IS_ENCRYPTED(dir) && |
---|
279 | 260 | (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) && |
---|
280 | 261 | !fscrypt_has_permitted_context(dir, inode)) { |
---|
281 | 262 | ubifs_warn(c, "Inconsistent encryption contexts: %lu/%lu", |
---|
.. | .. |
---|
373 | 354 | { |
---|
374 | 355 | struct inode *inode; |
---|
375 | 356 | struct ubifs_info *c = dir->i_sb->s_fs_info; |
---|
376 | | - struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1}; |
---|
| 357 | + struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, |
---|
| 358 | + .dirtied_ino = 1}; |
---|
377 | 359 | struct ubifs_budget_req ino_req = { .dirtied_ino = 1 }; |
---|
378 | 360 | struct ubifs_inode *ui, *dir_ui = ubifs_inode(dir); |
---|
379 | 361 | int err, instantiated = 0; |
---|
380 | 362 | struct fscrypt_name nm; |
---|
381 | 363 | |
---|
382 | 364 | /* |
---|
383 | | - * Budget request settings: new dirty inode, new direntry, |
---|
384 | | - * budget for dirtied inode will be released via writeback. |
---|
| 365 | + * Budget request settings: new inode, new direntry, changing the |
---|
| 366 | + * parent directory inode. |
---|
| 367 | + * Allocate budget separately for new dirtied inode, the budget will |
---|
| 368 | + * be released via writeback. |
---|
385 | 369 | */ |
---|
386 | 370 | |
---|
387 | 371 | dbg_gen("dent '%pd', mode %#hx in dir ino %lu", |
---|
.. | .. |
---|
442 | 426 | mutex_unlock(&dir_ui->ui_mutex); |
---|
443 | 427 | |
---|
444 | 428 | ubifs_release_budget(c, &req); |
---|
| 429 | + fscrypt_free_filename(&nm); |
---|
445 | 430 | |
---|
446 | 431 | return 0; |
---|
447 | 432 | |
---|
.. | .. |
---|
451 | 436 | make_bad_inode(inode); |
---|
452 | 437 | if (!instantiated) |
---|
453 | 438 | iput(inode); |
---|
| 439 | + else if (whiteout) |
---|
| 440 | + iput(*whiteout); |
---|
454 | 441 | out_budg: |
---|
455 | 442 | ubifs_release_budget(c, &req); |
---|
456 | 443 | if (!instantiated) |
---|
.. | .. |
---|
522 | 509 | struct ubifs_dent_node *dent; |
---|
523 | 510 | struct inode *dir = file_inode(file); |
---|
524 | 511 | struct ubifs_info *c = dir->i_sb->s_fs_info; |
---|
525 | | - bool encrypted = ubifs_crypt_is_encrypted(dir); |
---|
| 512 | + bool encrypted = IS_ENCRYPTED(dir); |
---|
526 | 513 | |
---|
527 | 514 | dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos); |
---|
528 | 515 | |
---|
.. | .. |
---|
534 | 521 | return 0; |
---|
535 | 522 | |
---|
536 | 523 | if (encrypted) { |
---|
537 | | - err = fscrypt_get_encryption_info(dir); |
---|
| 524 | + err = fscrypt_prepare_readdir(dir); |
---|
538 | 525 | if (err) |
---|
539 | 526 | return err; |
---|
540 | 527 | |
---|
541 | | - err = fscrypt_fname_alloc_buffer(dir, UBIFS_MAX_NLEN, &fstr); |
---|
| 528 | + err = fscrypt_fname_alloc_buffer(UBIFS_MAX_NLEN, &fstr); |
---|
542 | 529 | if (err) |
---|
543 | 530 | return err; |
---|
544 | 531 | |
---|
.. | .. |
---|
801 | 788 | dentry, inode->i_ino, |
---|
802 | 789 | inode->i_nlink, dir->i_ino); |
---|
803 | 790 | |
---|
804 | | - if (ubifs_crypt_is_encrypted(dir)) { |
---|
805 | | - err = fscrypt_get_encryption_info(dir); |
---|
806 | | - if (err && err != -ENOKEY) |
---|
807 | | - return err; |
---|
808 | | - } |
---|
809 | | - |
---|
810 | 791 | err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm); |
---|
| 792 | + if (err) |
---|
| 793 | + return err; |
---|
| 794 | + |
---|
| 795 | + err = ubifs_purge_xattrs(inode); |
---|
811 | 796 | if (err) |
---|
812 | 797 | return err; |
---|
813 | 798 | |
---|
.. | .. |
---|
911 | 896 | if (err) |
---|
912 | 897 | return err; |
---|
913 | 898 | |
---|
914 | | - if (ubifs_crypt_is_encrypted(dir)) { |
---|
915 | | - err = fscrypt_get_encryption_info(dir); |
---|
916 | | - if (err && err != -ENOKEY) |
---|
917 | | - return err; |
---|
918 | | - } |
---|
919 | | - |
---|
920 | 899 | err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm); |
---|
| 900 | + if (err) |
---|
| 901 | + return err; |
---|
| 902 | + |
---|
| 903 | + err = ubifs_purge_xattrs(inode); |
---|
921 | 904 | if (err) |
---|
922 | 905 | return err; |
---|
923 | 906 | |
---|
.. | .. |
---|
971 | 954 | struct ubifs_inode *dir_ui = ubifs_inode(dir); |
---|
972 | 955 | struct ubifs_info *c = dir->i_sb->s_fs_info; |
---|
973 | 956 | int err, sz_change; |
---|
974 | | - struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 }; |
---|
| 957 | + struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, |
---|
| 958 | + .dirtied_ino = 1}; |
---|
975 | 959 | struct fscrypt_name nm; |
---|
976 | 960 | |
---|
977 | 961 | /* |
---|
.. | .. |
---|
1135 | 1119 | int err, sz_change, len = strlen(symname); |
---|
1136 | 1120 | struct fscrypt_str disk_link; |
---|
1137 | 1121 | struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, |
---|
1138 | | - .new_ino_d = ALIGN(len, 8), |
---|
1139 | 1122 | .dirtied_ino = 1 }; |
---|
1140 | 1123 | struct fscrypt_name nm; |
---|
1141 | 1124 | |
---|
.. | .. |
---|
1151 | 1134 | * Budget request settings: new inode, new direntry and changing parent |
---|
1152 | 1135 | * directory inode. |
---|
1153 | 1136 | */ |
---|
| 1137 | + req.new_ino_d = ALIGN(disk_link.len - 1, 8); |
---|
1154 | 1138 | err = ubifs_budget_space(c, &req); |
---|
1155 | 1139 | if (err) |
---|
1156 | 1140 | return err; |
---|
.. | .. |
---|
1287 | 1271 | struct ubifs_budget_req ino_req = { .dirtied_ino = 1, |
---|
1288 | 1272 | .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) }; |
---|
1289 | 1273 | struct timespec64 time; |
---|
1290 | | - unsigned int uninitialized_var(saved_nlink); |
---|
| 1274 | + unsigned int saved_nlink; |
---|
1291 | 1275 | struct fscrypt_name old_nm, new_nm; |
---|
1292 | 1276 | |
---|
1293 | 1277 | /* |
---|
.. | .. |
---|
1303 | 1287 | old_dentry, old_inode->i_ino, old_dir->i_ino, |
---|
1304 | 1288 | new_dentry, new_dir->i_ino, flags); |
---|
1305 | 1289 | |
---|
1306 | | - if (unlink) |
---|
| 1290 | + if (unlink) { |
---|
1307 | 1291 | ubifs_assert(c, inode_is_locked(new_inode)); |
---|
| 1292 | + |
---|
| 1293 | + /* Budget for old inode's data when its nlink > 1. */ |
---|
| 1294 | + req.dirtied_ino_d = ALIGN(ubifs_inode(new_inode)->data_len, 8); |
---|
| 1295 | + err = ubifs_purge_xattrs(new_inode); |
---|
| 1296 | + if (err) |
---|
| 1297 | + return err; |
---|
| 1298 | + } |
---|
1308 | 1299 | |
---|
1309 | 1300 | if (unlink && is_dir) { |
---|
1310 | 1301 | err = ubifs_check_dir_empty(new_inode); |
---|
.. | .. |
---|
1341 | 1332 | |
---|
1342 | 1333 | if (flags & RENAME_WHITEOUT) { |
---|
1343 | 1334 | union ubifs_dev_desc *dev = NULL; |
---|
| 1335 | + struct ubifs_budget_req wht_req; |
---|
1344 | 1336 | |
---|
1345 | 1337 | dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); |
---|
1346 | 1338 | if (!dev) { |
---|
.. | .. |
---|
1362 | 1354 | whiteout_ui->data = dev; |
---|
1363 | 1355 | whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0)); |
---|
1364 | 1356 | ubifs_assert(c, !whiteout_ui->dirty); |
---|
| 1357 | + |
---|
| 1358 | + memset(&wht_req, 0, sizeof(struct ubifs_budget_req)); |
---|
| 1359 | + wht_req.dirtied_ino = 1; |
---|
| 1360 | + wht_req.dirtied_ino_d = ALIGN(whiteout_ui->data_len, 8); |
---|
| 1361 | + /* |
---|
| 1362 | + * To avoid deadlock between space budget (holds ui_mutex and |
---|
| 1363 | + * waits wb work) and writeback work(waits ui_mutex), do space |
---|
| 1364 | + * budget before ubifs inodes locked. |
---|
| 1365 | + */ |
---|
| 1366 | + err = ubifs_budget_space(c, &wht_req); |
---|
| 1367 | + if (err) { |
---|
| 1368 | + iput(whiteout); |
---|
| 1369 | + goto out_release; |
---|
| 1370 | + } |
---|
| 1371 | + |
---|
| 1372 | + /* Add the old_dentry size to the old_dir size. */ |
---|
| 1373 | + old_sz -= CALC_DENT_SIZE(fname_len(&old_nm)); |
---|
1365 | 1374 | } |
---|
1366 | 1375 | |
---|
1367 | 1376 | lock_4_inodes(old_dir, new_dir, new_inode, whiteout); |
---|
.. | .. |
---|
1436 | 1445 | } |
---|
1437 | 1446 | |
---|
1438 | 1447 | if (whiteout) { |
---|
1439 | | - struct ubifs_budget_req wht_req = { .dirtied_ino = 1, |
---|
1440 | | - .dirtied_ino_d = \ |
---|
1441 | | - ALIGN(ubifs_inode(whiteout)->data_len, 8) }; |
---|
1442 | | - |
---|
1443 | | - err = ubifs_budget_space(c, &wht_req); |
---|
1444 | | - if (err) { |
---|
1445 | | - kfree(whiteout_ui->data); |
---|
1446 | | - whiteout_ui->data_len = 0; |
---|
1447 | | - iput(whiteout); |
---|
1448 | | - goto out_release; |
---|
1449 | | - } |
---|
1450 | | - |
---|
1451 | 1448 | inc_nlink(whiteout); |
---|
1452 | 1449 | mark_inode_dirty(whiteout); |
---|
1453 | 1450 | |
---|
.. | .. |
---|
1537 | 1534 | return err; |
---|
1538 | 1535 | } |
---|
1539 | 1536 | |
---|
| 1537 | + err = ubifs_budget_space(c, &req); |
---|
| 1538 | + if (err) |
---|
| 1539 | + goto out; |
---|
| 1540 | + |
---|
1540 | 1541 | lock_4_inodes(old_dir, new_dir, NULL, NULL); |
---|
1541 | 1542 | |
---|
1542 | 1543 | time = current_time(old_dir); |
---|
.. | .. |
---|
1562 | 1563 | unlock_4_inodes(old_dir, new_dir, NULL, NULL); |
---|
1563 | 1564 | ubifs_release_budget(c, &req); |
---|
1564 | 1565 | |
---|
| 1566 | +out: |
---|
1565 | 1567 | fscrypt_free_filename(&fst_nm); |
---|
1566 | 1568 | fscrypt_free_filename(&snd_nm); |
---|
1567 | 1569 | return err; |
---|
.. | .. |
---|
1645 | 1647 | return 0; |
---|
1646 | 1648 | } |
---|
1647 | 1649 | |
---|
1648 | | -static int ubifs_dir_open(struct inode *dir, struct file *file) |
---|
1649 | | -{ |
---|
1650 | | - if (ubifs_crypt_is_encrypted(dir)) |
---|
1651 | | - return fscrypt_get_encryption_info(dir) ? -EACCES : 0; |
---|
1652 | | - |
---|
1653 | | - return 0; |
---|
1654 | | -} |
---|
1655 | | - |
---|
1656 | 1650 | const struct inode_operations ubifs_dir_inode_operations = { |
---|
1657 | 1651 | .lookup = ubifs_lookup, |
---|
1658 | 1652 | .create = ubifs_create, |
---|
.. | .. |
---|
1668 | 1662 | #ifdef CONFIG_UBIFS_FS_XATTR |
---|
1669 | 1663 | .listxattr = ubifs_listxattr, |
---|
1670 | 1664 | #endif |
---|
1671 | | -#ifdef CONFIG_UBIFS_ATIME_SUPPORT |
---|
1672 | 1665 | .update_time = ubifs_update_time, |
---|
1673 | | -#endif |
---|
1674 | 1666 | .tmpfile = ubifs_tmpfile, |
---|
1675 | 1667 | }; |
---|
1676 | 1668 | |
---|
.. | .. |
---|
1681 | 1673 | .iterate_shared = ubifs_readdir, |
---|
1682 | 1674 | .fsync = ubifs_fsync, |
---|
1683 | 1675 | .unlocked_ioctl = ubifs_ioctl, |
---|
1684 | | - .open = ubifs_dir_open, |
---|
1685 | 1676 | #ifdef CONFIG_COMPAT |
---|
1686 | 1677 | .compat_ioctl = ubifs_compat_ioctl, |
---|
1687 | 1678 | #endif |
---|
1688 | 1679 | }; |
---|
1689 | | - |
---|
1690 | | -#ifdef CONFIG_FS_ENCRYPTION |
---|
1691 | | -static const struct dentry_operations ubifs_encrypted_dentry_ops = { |
---|
1692 | | - .d_revalidate = fscrypt_d_revalidate, |
---|
1693 | | -}; |
---|
1694 | | -#endif |
---|
1695 | | - |
---|
1696 | | -static void ubifs_set_d_ops(struct inode *dir, struct dentry *dentry) |
---|
1697 | | -{ |
---|
1698 | | -#ifdef CONFIG_FS_ENCRYPTION |
---|
1699 | | - if (dentry->d_flags & DCACHE_ENCRYPTED_NAME) { |
---|
1700 | | - d_set_d_op(dentry, &ubifs_encrypted_dentry_ops); |
---|
1701 | | - return; |
---|
1702 | | - } |
---|
1703 | | -#endif |
---|
1704 | | -} |
---|