.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * (C) 1997 Linus Torvalds |
---|
3 | 4 | * (C) 1999 Andrea Arcangeli <andrea@suse.de> (dynamic inode allocation) |
---|
.. | .. |
---|
10 | 11 | #include <linux/swap.h> |
---|
11 | 12 | #include <linux/security.h> |
---|
12 | 13 | #include <linux/cdev.h> |
---|
13 | | -#include <linux/bootmem.h> |
---|
| 14 | +#include <linux/memblock.h> |
---|
14 | 15 | #include <linux/fscrypt.h> |
---|
15 | 16 | #include <linux/fsnotify.h> |
---|
16 | 17 | #include <linux/mount.h> |
---|
.. | .. |
---|
107 | 108 | */ |
---|
108 | 109 | #ifdef CONFIG_SYSCTL |
---|
109 | 110 | int proc_nr_inodes(struct ctl_table *table, int write, |
---|
110 | | - void __user *buffer, size_t *lenp, loff_t *ppos) |
---|
| 111 | + void *buffer, size_t *lenp, loff_t *ppos) |
---|
111 | 112 | { |
---|
112 | 113 | inodes_stat.nr_inodes = get_nr_inodes(); |
---|
113 | 114 | inodes_stat.nr_unused = get_nr_inodes_unused(); |
---|
.. | .. |
---|
167 | 168 | inode->i_wb_frn_history = 0; |
---|
168 | 169 | #endif |
---|
169 | 170 | |
---|
170 | | - if (security_inode_alloc(inode)) |
---|
171 | | - goto out; |
---|
172 | 171 | spin_lock_init(&inode->i_lock); |
---|
173 | 172 | lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); |
---|
174 | 173 | |
---|
.. | .. |
---|
180 | 179 | mapping->a_ops = &empty_aops; |
---|
181 | 180 | mapping->host = inode; |
---|
182 | 181 | mapping->flags = 0; |
---|
| 182 | + if (sb->s_type->fs_flags & FS_THP_SUPPORT) |
---|
| 183 | + __set_bit(AS_THP_SUPPORT, &mapping->flags); |
---|
183 | 184 | mapping->wb_err = 0; |
---|
184 | 185 | atomic_set(&mapping->i_mmap_writable, 0); |
---|
| 186 | +#ifdef CONFIG_READ_ONLY_THP_FOR_FS |
---|
| 187 | + atomic_set(&mapping->nr_thps, 0); |
---|
| 188 | +#endif |
---|
185 | 189 | mapping_set_gfp_mask(mapping, GFP_HIGHUSER_MOVABLE); |
---|
186 | 190 | mapping->private_data = NULL; |
---|
187 | 191 | mapping->writeback_index = 0; |
---|
.. | .. |
---|
196 | 200 | inode->i_fsnotify_mask = 0; |
---|
197 | 201 | #endif |
---|
198 | 202 | inode->i_flctx = NULL; |
---|
| 203 | + |
---|
| 204 | + if (unlikely(security_inode_alloc(inode))) |
---|
| 205 | + return -ENOMEM; |
---|
199 | 206 | this_cpu_inc(nr_inodes); |
---|
200 | 207 | |
---|
201 | 208 | return 0; |
---|
202 | | -out: |
---|
203 | | - return -ENOMEM; |
---|
204 | 209 | } |
---|
205 | 210 | EXPORT_SYMBOL(inode_init_always); |
---|
206 | 211 | |
---|
| 212 | +void free_inode_nonrcu(struct inode *inode) |
---|
| 213 | +{ |
---|
| 214 | + kmem_cache_free(inode_cachep, inode); |
---|
| 215 | +} |
---|
| 216 | +EXPORT_SYMBOL(free_inode_nonrcu); |
---|
| 217 | + |
---|
| 218 | +static void i_callback(struct rcu_head *head) |
---|
| 219 | +{ |
---|
| 220 | + struct inode *inode = container_of(head, struct inode, i_rcu); |
---|
| 221 | + if (inode->free_inode) |
---|
| 222 | + inode->free_inode(inode); |
---|
| 223 | + else |
---|
| 224 | + free_inode_nonrcu(inode); |
---|
| 225 | +} |
---|
| 226 | + |
---|
207 | 227 | static struct inode *alloc_inode(struct super_block *sb) |
---|
208 | 228 | { |
---|
| 229 | + const struct super_operations *ops = sb->s_op; |
---|
209 | 230 | struct inode *inode; |
---|
210 | 231 | |
---|
211 | | - if (sb->s_op->alloc_inode) |
---|
212 | | - inode = sb->s_op->alloc_inode(sb); |
---|
| 232 | + if (ops->alloc_inode) |
---|
| 233 | + inode = ops->alloc_inode(sb); |
---|
213 | 234 | else |
---|
214 | 235 | inode = kmem_cache_alloc(inode_cachep, GFP_KERNEL); |
---|
215 | 236 | |
---|
.. | .. |
---|
217 | 238 | return NULL; |
---|
218 | 239 | |
---|
219 | 240 | if (unlikely(inode_init_always(sb, inode))) { |
---|
220 | | - if (inode->i_sb->s_op->destroy_inode) |
---|
221 | | - inode->i_sb->s_op->destroy_inode(inode); |
---|
222 | | - else |
---|
223 | | - kmem_cache_free(inode_cachep, inode); |
---|
| 241 | + if (ops->destroy_inode) { |
---|
| 242 | + ops->destroy_inode(inode); |
---|
| 243 | + if (!ops->free_inode) |
---|
| 244 | + return NULL; |
---|
| 245 | + } |
---|
| 246 | + inode->free_inode = ops->free_inode; |
---|
| 247 | + i_callback(&inode->i_rcu); |
---|
224 | 248 | return NULL; |
---|
225 | 249 | } |
---|
226 | 250 | |
---|
227 | 251 | return inode; |
---|
228 | 252 | } |
---|
229 | | - |
---|
230 | | -void free_inode_nonrcu(struct inode *inode) |
---|
231 | | -{ |
---|
232 | | - kmem_cache_free(inode_cachep, inode); |
---|
233 | | -} |
---|
234 | | -EXPORT_SYMBOL(free_inode_nonrcu); |
---|
235 | 253 | |
---|
236 | 254 | void __destroy_inode(struct inode *inode) |
---|
237 | 255 | { |
---|
.. | .. |
---|
255 | 273 | } |
---|
256 | 274 | EXPORT_SYMBOL(__destroy_inode); |
---|
257 | 275 | |
---|
258 | | -static void i_callback(struct rcu_head *head) |
---|
259 | | -{ |
---|
260 | | - struct inode *inode = container_of(head, struct inode, i_rcu); |
---|
261 | | - kmem_cache_free(inode_cachep, inode); |
---|
262 | | -} |
---|
263 | | - |
---|
264 | 276 | static void destroy_inode(struct inode *inode) |
---|
265 | 277 | { |
---|
| 278 | + const struct super_operations *ops = inode->i_sb->s_op; |
---|
| 279 | + |
---|
266 | 280 | BUG_ON(!list_empty(&inode->i_lru)); |
---|
267 | 281 | __destroy_inode(inode); |
---|
268 | | - if (inode->i_sb->s_op->destroy_inode) |
---|
269 | | - inode->i_sb->s_op->destroy_inode(inode); |
---|
270 | | - else |
---|
271 | | - call_rcu(&inode->i_rcu, i_callback); |
---|
| 282 | + if (ops->destroy_inode) { |
---|
| 283 | + ops->destroy_inode(inode); |
---|
| 284 | + if (!ops->free_inode) |
---|
| 285 | + return; |
---|
| 286 | + } |
---|
| 287 | + inode->free_inode = ops->free_inode; |
---|
| 288 | + call_rcu(&inode->i_rcu, i_callback); |
---|
272 | 289 | } |
---|
273 | 290 | |
---|
274 | 291 | /** |
---|
.. | .. |
---|
289 | 306 | if (!inode->i_nlink) |
---|
290 | 307 | atomic_long_inc(&inode->i_sb->s_remove_count); |
---|
291 | 308 | } |
---|
292 | | -EXPORT_SYMBOL(drop_nlink); |
---|
| 309 | +EXPORT_SYMBOL_NS(drop_nlink, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
293 | 310 | |
---|
294 | 311 | /** |
---|
295 | 312 | * clear_nlink - directly zero an inode's link count |
---|
.. | .. |
---|
328 | 345 | inode->__i_nlink = nlink; |
---|
329 | 346 | } |
---|
330 | 347 | } |
---|
331 | | -EXPORT_SYMBOL(set_nlink); |
---|
| 348 | +EXPORT_SYMBOL_NS(set_nlink, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
332 | 349 | |
---|
333 | 350 | /** |
---|
334 | 351 | * inc_nlink - directly increment an inode's link count |
---|
.. | .. |
---|
351 | 368 | |
---|
352 | 369 | static void __address_space_init_once(struct address_space *mapping) |
---|
353 | 370 | { |
---|
354 | | - INIT_RADIX_TREE(&mapping->i_pages, GFP_ATOMIC | __GFP_ACCOUNT); |
---|
| 371 | + xa_init_flags(&mapping->i_pages, XA_FLAGS_LOCK_IRQ | XA_FLAGS_ACCOUNT); |
---|
355 | 372 | init_rwsem(&mapping->i_mmap_rwsem); |
---|
356 | 373 | INIT_LIST_HEAD(&mapping->private_list); |
---|
357 | 374 | spin_lock_init(&mapping->private_lock); |
---|
.. | .. |
---|
381 | 398 | __address_space_init_once(&inode->i_data); |
---|
382 | 399 | i_size_ordered_init(inode); |
---|
383 | 400 | } |
---|
384 | | -EXPORT_SYMBOL(inode_init_once); |
---|
| 401 | +EXPORT_SYMBOL_NS(inode_init_once, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
385 | 402 | |
---|
386 | 403 | static void init_once(void *foo) |
---|
387 | 404 | { |
---|
.. | .. |
---|
405 | 422 | { |
---|
406 | 423 | WARN_ON(atomic_inc_return(&inode->i_count) < 2); |
---|
407 | 424 | } |
---|
408 | | -EXPORT_SYMBOL(ihold); |
---|
| 425 | +EXPORT_SYMBOL_NS(ihold, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
409 | 426 | |
---|
410 | 427 | static void inode_lru_list_add(struct inode *inode) |
---|
411 | 428 | { |
---|
.. | .. |
---|
481 | 498 | |
---|
482 | 499 | spin_lock(&inode_hash_lock); |
---|
483 | 500 | spin_lock(&inode->i_lock); |
---|
484 | | - hlist_add_head(&inode->i_hash, b); |
---|
| 501 | + hlist_add_head_rcu(&inode->i_hash, b); |
---|
485 | 502 | spin_unlock(&inode->i_lock); |
---|
486 | 503 | spin_unlock(&inode_hash_lock); |
---|
487 | 504 | } |
---|
488 | | -EXPORT_SYMBOL(__insert_inode_hash); |
---|
| 505 | +EXPORT_SYMBOL_NS(__insert_inode_hash, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
489 | 506 | |
---|
490 | 507 | /** |
---|
491 | 508 | * __remove_inode_hash - remove an inode from the hash |
---|
.. | .. |
---|
497 | 514 | { |
---|
498 | 515 | spin_lock(&inode_hash_lock); |
---|
499 | 516 | spin_lock(&inode->i_lock); |
---|
500 | | - hlist_del_init(&inode->i_hash); |
---|
| 517 | + hlist_del_init_rcu(&inode->i_hash); |
---|
501 | 518 | spin_unlock(&inode->i_lock); |
---|
502 | 519 | spin_unlock(&inode_hash_lock); |
---|
503 | 520 | } |
---|
504 | | -EXPORT_SYMBOL(__remove_inode_hash); |
---|
| 521 | +EXPORT_SYMBOL_NS(__remove_inode_hash, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
505 | 522 | |
---|
506 | 523 | void clear_inode(struct inode *inode) |
---|
507 | 524 | { |
---|
.. | .. |
---|
521 | 538 | /* don't need i_lock here, no concurrent mods to i_state */ |
---|
522 | 539 | inode->i_state = I_FREEING | I_CLEAR; |
---|
523 | 540 | } |
---|
524 | | -EXPORT_SYMBOL(clear_inode); |
---|
| 541 | +EXPORT_SYMBOL_NS(clear_inode, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
525 | 542 | |
---|
526 | 543 | /* |
---|
527 | 544 | * Free the inode passed in, removing it from the lists it is still connected |
---|
.. | .. |
---|
983 | 1000 | wake_up_bit(&inode->i_state, __I_NEW); |
---|
984 | 1001 | spin_unlock(&inode->i_lock); |
---|
985 | 1002 | } |
---|
986 | | -EXPORT_SYMBOL(unlock_new_inode); |
---|
| 1003 | +EXPORT_SYMBOL_NS(unlock_new_inode, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
987 | 1004 | |
---|
988 | 1005 | void discard_new_inode(struct inode *inode) |
---|
989 | 1006 | { |
---|
.. | .. |
---|
997 | 1014 | iput(inode); |
---|
998 | 1015 | } |
---|
999 | 1016 | EXPORT_SYMBOL(discard_new_inode); |
---|
| 1017 | + |
---|
| 1018 | +/** |
---|
| 1019 | + * lock_two_inodes - lock two inodes (may be regular files but also dirs) |
---|
| 1020 | + * |
---|
| 1021 | + * Lock any non-NULL argument. The caller must make sure that if he is passing |
---|
| 1022 | + * in two directories, one is not ancestor of the other. Zero, one or two |
---|
| 1023 | + * objects may be locked by this function. |
---|
| 1024 | + * |
---|
| 1025 | + * @inode1: first inode to lock |
---|
| 1026 | + * @inode2: second inode to lock |
---|
| 1027 | + * @subclass1: inode lock subclass for the first lock obtained |
---|
| 1028 | + * @subclass2: inode lock subclass for the second lock obtained |
---|
| 1029 | + */ |
---|
| 1030 | +void lock_two_inodes(struct inode *inode1, struct inode *inode2, |
---|
| 1031 | + unsigned subclass1, unsigned subclass2) |
---|
| 1032 | +{ |
---|
| 1033 | + if (!inode1 || !inode2) { |
---|
| 1034 | + /* |
---|
| 1035 | + * Make sure @subclass1 will be used for the acquired lock. |
---|
| 1036 | + * This is not strictly necessary (no current caller cares) but |
---|
| 1037 | + * let's keep things consistent. |
---|
| 1038 | + */ |
---|
| 1039 | + if (!inode1) |
---|
| 1040 | + swap(inode1, inode2); |
---|
| 1041 | + goto lock; |
---|
| 1042 | + } |
---|
| 1043 | + |
---|
| 1044 | + /* |
---|
| 1045 | + * If one object is directory and the other is not, we must make sure |
---|
| 1046 | + * to lock directory first as the other object may be its child. |
---|
| 1047 | + */ |
---|
| 1048 | + if (S_ISDIR(inode2->i_mode) == S_ISDIR(inode1->i_mode)) { |
---|
| 1049 | + if (inode1 > inode2) |
---|
| 1050 | + swap(inode1, inode2); |
---|
| 1051 | + } else if (!S_ISDIR(inode1->i_mode)) |
---|
| 1052 | + swap(inode1, inode2); |
---|
| 1053 | +lock: |
---|
| 1054 | + if (inode1) |
---|
| 1055 | + inode_lock_nested(inode1, subclass1); |
---|
| 1056 | + if (inode2 && inode2 != inode1) |
---|
| 1057 | + inode_lock_nested(inode2, subclass2); |
---|
| 1058 | +} |
---|
1000 | 1059 | |
---|
1001 | 1060 | /** |
---|
1002 | 1061 | * lock_two_nondirectories - take two i_mutexes on non-directory objects |
---|
.. | .. |
---|
1091 | 1150 | */ |
---|
1092 | 1151 | spin_lock(&inode->i_lock); |
---|
1093 | 1152 | inode->i_state |= I_NEW; |
---|
1094 | | - hlist_add_head(&inode->i_hash, head); |
---|
| 1153 | + hlist_add_head_rcu(&inode->i_hash, head); |
---|
1095 | 1154 | spin_unlock(&inode->i_lock); |
---|
1096 | 1155 | if (!creating) |
---|
1097 | 1156 | inode_sb_list_add(inode); |
---|
.. | .. |
---|
1140 | 1199 | } |
---|
1141 | 1200 | return inode; |
---|
1142 | 1201 | } |
---|
1143 | | -EXPORT_SYMBOL(iget5_locked); |
---|
| 1202 | +EXPORT_SYMBOL_NS(iget5_locked, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
1144 | 1203 | |
---|
1145 | 1204 | /** |
---|
1146 | 1205 | * iget_locked - obtain an inode from a mounted file system |
---|
.. | .. |
---|
1185 | 1244 | inode->i_ino = ino; |
---|
1186 | 1245 | spin_lock(&inode->i_lock); |
---|
1187 | 1246 | inode->i_state = I_NEW; |
---|
1188 | | - hlist_add_head(&inode->i_hash, head); |
---|
| 1247 | + hlist_add_head_rcu(&inode->i_hash, head); |
---|
1189 | 1248 | spin_unlock(&inode->i_lock); |
---|
1190 | 1249 | inode_sb_list_add(inode); |
---|
1191 | 1250 | spin_unlock(&inode_hash_lock); |
---|
.. | .. |
---|
1228 | 1287 | struct hlist_head *b = inode_hashtable + hash(sb, ino); |
---|
1229 | 1288 | struct inode *inode; |
---|
1230 | 1289 | |
---|
1231 | | - spin_lock(&inode_hash_lock); |
---|
1232 | | - hlist_for_each_entry(inode, b, i_hash) { |
---|
1233 | | - if (inode->i_ino == ino && inode->i_sb == sb) { |
---|
1234 | | - spin_unlock(&inode_hash_lock); |
---|
| 1290 | + hlist_for_each_entry_rcu(inode, b, i_hash) { |
---|
| 1291 | + if (inode->i_ino == ino && inode->i_sb == sb) |
---|
1235 | 1292 | return 0; |
---|
1236 | | - } |
---|
1237 | 1293 | } |
---|
1238 | | - spin_unlock(&inode_hash_lock); |
---|
1239 | | - |
---|
1240 | 1294 | return 1; |
---|
1241 | 1295 | } |
---|
1242 | 1296 | |
---|
.. | .. |
---|
1265 | 1319 | static unsigned int counter; |
---|
1266 | 1320 | ino_t res; |
---|
1267 | 1321 | |
---|
| 1322 | + rcu_read_lock(); |
---|
1268 | 1323 | spin_lock(&iunique_lock); |
---|
1269 | 1324 | do { |
---|
1270 | 1325 | if (counter <= max_reserved) |
---|
.. | .. |
---|
1272 | 1327 | res = counter++; |
---|
1273 | 1328 | } while (!test_inode_iunique(sb, res)); |
---|
1274 | 1329 | spin_unlock(&iunique_lock); |
---|
| 1330 | + rcu_read_unlock(); |
---|
1275 | 1331 | |
---|
1276 | 1332 | return res; |
---|
1277 | 1333 | } |
---|
1278 | | -EXPORT_SYMBOL(iunique); |
---|
| 1334 | +EXPORT_SYMBOL_NS(iunique, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
1279 | 1335 | |
---|
1280 | 1336 | struct inode *igrab(struct inode *inode) |
---|
1281 | 1337 | { |
---|
.. | .. |
---|
1358 | 1414 | } |
---|
1359 | 1415 | return inode; |
---|
1360 | 1416 | } |
---|
1361 | | -EXPORT_SYMBOL(ilookup5); |
---|
| 1417 | +EXPORT_SYMBOL_NS(ilookup5, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
1362 | 1418 | |
---|
1363 | 1419 | /** |
---|
1364 | 1420 | * ilookup - search for an inode in the inode cache |
---|
.. | .. |
---|
1440 | 1496 | } |
---|
1441 | 1497 | EXPORT_SYMBOL(find_inode_nowait); |
---|
1442 | 1498 | |
---|
| 1499 | +/** |
---|
| 1500 | + * find_inode_rcu - find an inode in the inode cache |
---|
| 1501 | + * @sb: Super block of file system to search |
---|
| 1502 | + * @hashval: Key to hash |
---|
| 1503 | + * @test: Function to test match on an inode |
---|
| 1504 | + * @data: Data for test function |
---|
| 1505 | + * |
---|
| 1506 | + * Search for the inode specified by @hashval and @data in the inode cache, |
---|
| 1507 | + * where the helper function @test will return 0 if the inode does not match |
---|
| 1508 | + * and 1 if it does. The @test function must be responsible for taking the |
---|
| 1509 | + * i_lock spin_lock and checking i_state for an inode being freed or being |
---|
| 1510 | + * initialized. |
---|
| 1511 | + * |
---|
| 1512 | + * If successful, this will return the inode for which the @test function |
---|
| 1513 | + * returned 1 and NULL otherwise. |
---|
| 1514 | + * |
---|
| 1515 | + * The @test function is not permitted to take a ref on any inode presented. |
---|
| 1516 | + * It is also not permitted to sleep. |
---|
| 1517 | + * |
---|
| 1518 | + * The caller must hold the RCU read lock. |
---|
| 1519 | + */ |
---|
| 1520 | +struct inode *find_inode_rcu(struct super_block *sb, unsigned long hashval, |
---|
| 1521 | + int (*test)(struct inode *, void *), void *data) |
---|
| 1522 | +{ |
---|
| 1523 | + struct hlist_head *head = inode_hashtable + hash(sb, hashval); |
---|
| 1524 | + struct inode *inode; |
---|
| 1525 | + |
---|
| 1526 | + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), |
---|
| 1527 | + "suspicious find_inode_rcu() usage"); |
---|
| 1528 | + |
---|
| 1529 | + hlist_for_each_entry_rcu(inode, head, i_hash) { |
---|
| 1530 | + if (inode->i_sb == sb && |
---|
| 1531 | + !(READ_ONCE(inode->i_state) & (I_FREEING | I_WILL_FREE)) && |
---|
| 1532 | + test(inode, data)) |
---|
| 1533 | + return inode; |
---|
| 1534 | + } |
---|
| 1535 | + return NULL; |
---|
| 1536 | +} |
---|
| 1537 | +EXPORT_SYMBOL(find_inode_rcu); |
---|
| 1538 | + |
---|
| 1539 | +/** |
---|
| 1540 | + * find_inode_by_rcu - Find an inode in the inode cache |
---|
| 1541 | + * @sb: Super block of file system to search |
---|
| 1542 | + * @ino: The inode number to match |
---|
| 1543 | + * |
---|
| 1544 | + * Search for the inode specified by @hashval and @data in the inode cache, |
---|
| 1545 | + * where the helper function @test will return 0 if the inode does not match |
---|
| 1546 | + * and 1 if it does. The @test function must be responsible for taking the |
---|
| 1547 | + * i_lock spin_lock and checking i_state for an inode being freed or being |
---|
| 1548 | + * initialized. |
---|
| 1549 | + * |
---|
| 1550 | + * If successful, this will return the inode for which the @test function |
---|
| 1551 | + * returned 1 and NULL otherwise. |
---|
| 1552 | + * |
---|
| 1553 | + * The @test function is not permitted to take a ref on any inode presented. |
---|
| 1554 | + * It is also not permitted to sleep. |
---|
| 1555 | + * |
---|
| 1556 | + * The caller must hold the RCU read lock. |
---|
| 1557 | + */ |
---|
| 1558 | +struct inode *find_inode_by_ino_rcu(struct super_block *sb, |
---|
| 1559 | + unsigned long ino) |
---|
| 1560 | +{ |
---|
| 1561 | + struct hlist_head *head = inode_hashtable + hash(sb, ino); |
---|
| 1562 | + struct inode *inode; |
---|
| 1563 | + |
---|
| 1564 | + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), |
---|
| 1565 | + "suspicious find_inode_by_ino_rcu() usage"); |
---|
| 1566 | + |
---|
| 1567 | + hlist_for_each_entry_rcu(inode, head, i_hash) { |
---|
| 1568 | + if (inode->i_ino == ino && |
---|
| 1569 | + inode->i_sb == sb && |
---|
| 1570 | + !(READ_ONCE(inode->i_state) & (I_FREEING | I_WILL_FREE))) |
---|
| 1571 | + return inode; |
---|
| 1572 | + } |
---|
| 1573 | + return NULL; |
---|
| 1574 | +} |
---|
| 1575 | +EXPORT_SYMBOL(find_inode_by_ino_rcu); |
---|
| 1576 | + |
---|
1443 | 1577 | int insert_inode_locked(struct inode *inode) |
---|
1444 | 1578 | { |
---|
1445 | 1579 | struct super_block *sb = inode->i_sb; |
---|
.. | .. |
---|
1464 | 1598 | if (likely(!old)) { |
---|
1465 | 1599 | spin_lock(&inode->i_lock); |
---|
1466 | 1600 | inode->i_state |= I_NEW | I_CREATING; |
---|
1467 | | - hlist_add_head(&inode->i_hash, head); |
---|
| 1601 | + hlist_add_head_rcu(&inode->i_hash, head); |
---|
1468 | 1602 | spin_unlock(&inode->i_lock); |
---|
1469 | 1603 | spin_unlock(&inode_hash_lock); |
---|
1470 | 1604 | return 0; |
---|
.. | .. |
---|
1524 | 1658 | { |
---|
1525 | 1659 | struct super_block *sb = inode->i_sb; |
---|
1526 | 1660 | const struct super_operations *op = inode->i_sb->s_op; |
---|
| 1661 | + unsigned long state; |
---|
1527 | 1662 | int drop; |
---|
1528 | 1663 | |
---|
1529 | 1664 | WARN_ON(inode->i_state & I_NEW); |
---|
.. | .. |
---|
1533 | 1668 | else |
---|
1534 | 1669 | drop = generic_drop_inode(inode); |
---|
1535 | 1670 | |
---|
1536 | | - if (!drop && (sb->s_flags & SB_ACTIVE)) { |
---|
| 1671 | + if (!drop && |
---|
| 1672 | + !(inode->i_state & I_DONTCACHE) && |
---|
| 1673 | + (sb->s_flags & SB_ACTIVE)) { |
---|
1537 | 1674 | inode_add_lru(inode); |
---|
1538 | 1675 | spin_unlock(&inode->i_lock); |
---|
1539 | 1676 | return; |
---|
1540 | 1677 | } |
---|
1541 | 1678 | |
---|
| 1679 | + state = inode->i_state; |
---|
1542 | 1680 | if (!drop) { |
---|
1543 | | - inode->i_state |= I_WILL_FREE; |
---|
| 1681 | + WRITE_ONCE(inode->i_state, state | I_WILL_FREE); |
---|
1544 | 1682 | spin_unlock(&inode->i_lock); |
---|
| 1683 | + |
---|
1545 | 1684 | write_inode_now(inode, 1); |
---|
| 1685 | + |
---|
1546 | 1686 | spin_lock(&inode->i_lock); |
---|
1547 | | - WARN_ON(inode->i_state & I_NEW); |
---|
1548 | | - inode->i_state &= ~I_WILL_FREE; |
---|
| 1687 | + state = inode->i_state; |
---|
| 1688 | + WARN_ON(state & I_NEW); |
---|
| 1689 | + state &= ~I_WILL_FREE; |
---|
1549 | 1690 | } |
---|
1550 | 1691 | |
---|
1551 | | - inode->i_state |= I_FREEING; |
---|
| 1692 | + WRITE_ONCE(inode->i_state, state | I_FREEING); |
---|
1552 | 1693 | if (!list_empty(&inode->i_lru)) |
---|
1553 | 1694 | inode_lru_list_del(inode); |
---|
1554 | 1695 | spin_unlock(&inode->i_lock); |
---|
.. | .. |
---|
1584 | 1725 | } |
---|
1585 | 1726 | EXPORT_SYMBOL(iput); |
---|
1586 | 1727 | |
---|
| 1728 | +#ifdef CONFIG_BLOCK |
---|
1587 | 1729 | /** |
---|
1588 | 1730 | * bmap - find a block number in a file |
---|
1589 | | - * @inode: inode of file |
---|
1590 | | - * @block: block to find |
---|
| 1731 | + * @inode: inode owning the block number being requested |
---|
| 1732 | + * @block: pointer containing the block to find |
---|
1591 | 1733 | * |
---|
1592 | | - * Returns the block number on the device holding the inode that |
---|
1593 | | - * is the disk block number for the block of the file requested. |
---|
1594 | | - * That is, asked for block 4 of inode 1 the function will return the |
---|
1595 | | - * disk block relative to the disk start that holds that block of the |
---|
1596 | | - * file. |
---|
| 1734 | + * Replaces the value in ``*block`` with the block number on the device holding |
---|
| 1735 | + * corresponding to the requested block number in the file. |
---|
| 1736 | + * That is, asked for block 4 of inode 1 the function will replace the |
---|
| 1737 | + * 4 in ``*block``, with disk block relative to the disk start that holds that |
---|
| 1738 | + * block of the file. |
---|
| 1739 | + * |
---|
| 1740 | + * Returns -EINVAL in case of error, 0 otherwise. If mapping falls into a |
---|
| 1741 | + * hole, returns 0 and ``*block`` is also set to 0. |
---|
1597 | 1742 | */ |
---|
1598 | | -sector_t bmap(struct inode *inode, sector_t block) |
---|
| 1743 | +int bmap(struct inode *inode, sector_t *block) |
---|
1599 | 1744 | { |
---|
1600 | | - sector_t res = 0; |
---|
1601 | | - if (inode->i_mapping->a_ops->bmap) |
---|
1602 | | - res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block); |
---|
1603 | | - return res; |
---|
| 1745 | + if (!inode->i_mapping->a_ops->bmap) |
---|
| 1746 | + return -EINVAL; |
---|
| 1747 | + |
---|
| 1748 | + *block = inode->i_mapping->a_ops->bmap(inode->i_mapping, *block); |
---|
| 1749 | + return 0; |
---|
1604 | 1750 | } |
---|
1605 | 1751 | EXPORT_SYMBOL(bmap); |
---|
| 1752 | +#endif |
---|
1606 | 1753 | |
---|
1607 | 1754 | /* |
---|
1608 | 1755 | * With relative atime, only update atime if the previous atime is |
---|
.. | .. |
---|
1610 | 1757 | * passed since the last atime update. |
---|
1611 | 1758 | */ |
---|
1612 | 1759 | static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, |
---|
1613 | | - struct timespec now) |
---|
| 1760 | + struct timespec64 now) |
---|
1614 | 1761 | { |
---|
1615 | 1762 | |
---|
1616 | 1763 | if (!(mnt->mnt_flags & MNT_RELATIME)) |
---|
.. | .. |
---|
1666 | 1813 | * This does the actual work of updating an inodes time or version. Must have |
---|
1667 | 1814 | * had called mnt_want_write() before calling this. |
---|
1668 | 1815 | */ |
---|
1669 | | -static int update_time(struct inode *inode, struct timespec64 *time, int flags) |
---|
| 1816 | +int inode_update_time(struct inode *inode, struct timespec64 *time, int flags) |
---|
1670 | 1817 | { |
---|
1671 | | - int (*update_time)(struct inode *, struct timespec64 *, int); |
---|
1672 | | - |
---|
1673 | | - update_time = inode->i_op->update_time ? inode->i_op->update_time : |
---|
1674 | | - generic_update_time; |
---|
1675 | | - |
---|
1676 | | - return update_time(inode, time, flags); |
---|
| 1818 | + if (inode->i_op->update_time) |
---|
| 1819 | + return inode->i_op->update_time(inode, time, flags); |
---|
| 1820 | + return generic_update_time(inode, time, flags); |
---|
1677 | 1821 | } |
---|
| 1822 | +EXPORT_SYMBOL(inode_update_time); |
---|
1678 | 1823 | |
---|
1679 | 1824 | /** |
---|
1680 | 1825 | * touch_atime - update the access time |
---|
.. | .. |
---|
1711 | 1856 | |
---|
1712 | 1857 | now = current_time(inode); |
---|
1713 | 1858 | |
---|
1714 | | - if (!relatime_need_update(mnt, inode, timespec64_to_timespec(now))) |
---|
| 1859 | + if (!relatime_need_update(mnt, inode, now)) |
---|
1715 | 1860 | return false; |
---|
1716 | 1861 | |
---|
1717 | 1862 | if (timespec64_equal(&inode->i_atime, &now)) |
---|
.. | .. |
---|
1744 | 1889 | * of the fs read only, e.g. subvolumes in Btrfs. |
---|
1745 | 1890 | */ |
---|
1746 | 1891 | now = current_time(inode); |
---|
1747 | | - update_time(inode, &now, S_ATIME); |
---|
| 1892 | + inode_update_time(inode, &now, S_ATIME); |
---|
1748 | 1893 | __mnt_drop_write(mnt); |
---|
1749 | 1894 | skip_update: |
---|
1750 | 1895 | sb_end_write(inode->i_sb); |
---|
1751 | 1896 | } |
---|
1752 | | -EXPORT_SYMBOL(touch_atime); |
---|
1753 | | - |
---|
1754 | | -/* |
---|
1755 | | - * The logic we want is |
---|
1756 | | - * |
---|
1757 | | - * if suid or (sgid and xgrp) |
---|
1758 | | - * remove privs |
---|
1759 | | - */ |
---|
1760 | | -int should_remove_suid(struct dentry *dentry) |
---|
1761 | | -{ |
---|
1762 | | - umode_t mode = d_inode(dentry)->i_mode; |
---|
1763 | | - int kill = 0; |
---|
1764 | | - |
---|
1765 | | - /* suid always must be killed */ |
---|
1766 | | - if (unlikely(mode & S_ISUID)) |
---|
1767 | | - kill = ATTR_KILL_SUID; |
---|
1768 | | - |
---|
1769 | | - /* |
---|
1770 | | - * sgid without any exec bits is just a mandatory locking mark; leave |
---|
1771 | | - * it alone. If some exec bits are set, it's a real sgid; kill it. |
---|
1772 | | - */ |
---|
1773 | | - if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) |
---|
1774 | | - kill |= ATTR_KILL_SGID; |
---|
1775 | | - |
---|
1776 | | - if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode))) |
---|
1777 | | - return kill; |
---|
1778 | | - |
---|
1779 | | - return 0; |
---|
1780 | | -} |
---|
1781 | | -EXPORT_SYMBOL(should_remove_suid); |
---|
| 1897 | +EXPORT_SYMBOL_NS(touch_atime, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
1782 | 1898 | |
---|
1783 | 1899 | /* |
---|
1784 | 1900 | * Return mask of changes for notify_change() that need to be done as a |
---|
.. | .. |
---|
1794 | 1910 | if (IS_NOSEC(inode)) |
---|
1795 | 1911 | return 0; |
---|
1796 | 1912 | |
---|
1797 | | - mask = should_remove_suid(dentry); |
---|
| 1913 | + mask = setattr_should_drop_suidgid(inode); |
---|
1798 | 1914 | ret = security_inode_need_killpriv(dentry); |
---|
1799 | 1915 | if (ret < 0) |
---|
1800 | 1916 | return ret; |
---|
.. | .. |
---|
1803 | 1919 | return mask; |
---|
1804 | 1920 | } |
---|
1805 | 1921 | |
---|
1806 | | -static int __remove_privs(struct vfsmount *mnt, struct dentry *dentry, int kill) |
---|
| 1922 | +static int __remove_privs(struct dentry *dentry, int kill) |
---|
1807 | 1923 | { |
---|
1808 | 1924 | struct iattr newattrs; |
---|
1809 | 1925 | |
---|
.. | .. |
---|
1812 | 1928 | * Note we call this on write, so notify_change will not |
---|
1813 | 1929 | * encounter any conflicting delegations: |
---|
1814 | 1930 | */ |
---|
1815 | | - return notify_change2(mnt, dentry, &newattrs, NULL); |
---|
| 1931 | + return notify_change(dentry, &newattrs, NULL); |
---|
1816 | 1932 | } |
---|
1817 | 1933 | |
---|
1818 | 1934 | /* |
---|
.. | .. |
---|
1839 | 1955 | if (kill < 0) |
---|
1840 | 1956 | return kill; |
---|
1841 | 1957 | if (kill) |
---|
1842 | | - error = __remove_privs(file->f_path.mnt, dentry, kill); |
---|
| 1958 | + error = __remove_privs(dentry, kill); |
---|
1843 | 1959 | if (!error) |
---|
1844 | 1960 | inode_has_no_xattr(inode); |
---|
1845 | 1961 | |
---|
1846 | 1962 | return error; |
---|
1847 | 1963 | } |
---|
1848 | | -EXPORT_SYMBOL(file_remove_privs); |
---|
| 1964 | +EXPORT_SYMBOL_NS(file_remove_privs, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
1849 | 1965 | |
---|
1850 | 1966 | /** |
---|
1851 | 1967 | * file_update_time - update mtime and ctime time |
---|
.. | .. |
---|
1888 | 2004 | if (__mnt_want_write_file(file)) |
---|
1889 | 2005 | return 0; |
---|
1890 | 2006 | |
---|
1891 | | - ret = update_time(inode, &now, sync_it); |
---|
| 2007 | + ret = inode_update_time(inode, &now, sync_it); |
---|
1892 | 2008 | __mnt_drop_write_file(file); |
---|
1893 | 2009 | |
---|
1894 | 2010 | return ret; |
---|
1895 | 2011 | } |
---|
1896 | 2012 | EXPORT_SYMBOL(file_update_time); |
---|
| 2013 | + |
---|
| 2014 | +/* Caller must hold the file's inode lock */ |
---|
| 2015 | +int file_modified(struct file *file) |
---|
| 2016 | +{ |
---|
| 2017 | + int err; |
---|
| 2018 | + |
---|
| 2019 | + /* |
---|
| 2020 | + * Clear the security bits if the process is not being run by root. |
---|
| 2021 | + * This keeps people from modifying setuid and setgid binaries. |
---|
| 2022 | + */ |
---|
| 2023 | + err = file_remove_privs(file); |
---|
| 2024 | + if (err) |
---|
| 2025 | + return err; |
---|
| 2026 | + |
---|
| 2027 | + if (unlikely(file->f_mode & FMODE_NOCMTIME)) |
---|
| 2028 | + return 0; |
---|
| 2029 | + |
---|
| 2030 | + return file_update_time(file); |
---|
| 2031 | +} |
---|
| 2032 | +EXPORT_SYMBOL(file_modified); |
---|
1897 | 2033 | |
---|
1898 | 2034 | int inode_needs_sync(struct inode *inode) |
---|
1899 | 2035 | { |
---|
.. | .. |
---|
2006 | 2142 | " inode %s:%lu\n", mode, inode->i_sb->s_id, |
---|
2007 | 2143 | inode->i_ino); |
---|
2008 | 2144 | } |
---|
2009 | | -EXPORT_SYMBOL(init_special_inode); |
---|
| 2145 | +EXPORT_SYMBOL_NS(init_special_inode, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
2010 | 2146 | |
---|
2011 | 2147 | /** |
---|
2012 | 2148 | * inode_init_owner - Init uid,gid,mode for new inode according to posix standards |
---|
.. | .. |
---|
2024 | 2160 | /* Directories are special, and always inherit S_ISGID */ |
---|
2025 | 2161 | if (S_ISDIR(mode)) |
---|
2026 | 2162 | mode |= S_ISGID; |
---|
2027 | | - else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && |
---|
2028 | | - !in_group_p(inode->i_gid) && |
---|
2029 | | - !capable_wrt_inode_uidgid(dir, CAP_FSETID)) |
---|
2030 | | - mode &= ~S_ISGID; |
---|
2031 | 2163 | } else |
---|
2032 | 2164 | inode->i_gid = current_fsgid(); |
---|
2033 | 2165 | inode->i_mode = mode; |
---|
2034 | 2166 | } |
---|
2035 | | -EXPORT_SYMBOL(inode_init_owner); |
---|
| 2167 | +EXPORT_SYMBOL_NS(inode_init_owner, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
2036 | 2168 | |
---|
2037 | 2169 | /** |
---|
2038 | 2170 | * inode_owner_or_capable - check current task permissions to inode |
---|
.. | .. |
---|
2086 | 2218 | if (atomic_read(&inode->i_dio_count)) |
---|
2087 | 2219 | __inode_dio_wait(inode); |
---|
2088 | 2220 | } |
---|
2089 | | -EXPORT_SYMBOL(inode_dio_wait); |
---|
| 2221 | +EXPORT_SYMBOL_NS(inode_dio_wait, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
2090 | 2222 | |
---|
2091 | 2223 | /* |
---|
2092 | 2224 | * inode_set_flags - atomically set some inode flags |
---|
.. | .. |
---|
2107 | 2239 | void inode_set_flags(struct inode *inode, unsigned int flags, |
---|
2108 | 2240 | unsigned int mask) |
---|
2109 | 2241 | { |
---|
2110 | | - unsigned int old_flags, new_flags; |
---|
2111 | | - |
---|
2112 | 2242 | WARN_ON_ONCE(flags & ~mask); |
---|
2113 | | - do { |
---|
2114 | | - old_flags = READ_ONCE(inode->i_flags); |
---|
2115 | | - new_flags = (old_flags & ~mask) | flags; |
---|
2116 | | - } while (unlikely(cmpxchg(&inode->i_flags, old_flags, |
---|
2117 | | - new_flags) != old_flags)); |
---|
| 2243 | + set_mask_bits(&inode->i_flags, mask, flags); |
---|
2118 | 2244 | } |
---|
2119 | | -EXPORT_SYMBOL(inode_set_flags); |
---|
| 2245 | +EXPORT_SYMBOL_NS(inode_set_flags, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
2120 | 2246 | |
---|
2121 | 2247 | void inode_nohighmem(struct inode *inode) |
---|
2122 | 2248 | { |
---|
.. | .. |
---|
2125 | 2251 | EXPORT_SYMBOL(inode_nohighmem); |
---|
2126 | 2252 | |
---|
2127 | 2253 | /** |
---|
2128 | | - * timespec64_trunc - Truncate timespec64 to a granularity |
---|
2129 | | - * @t: Timespec64 |
---|
2130 | | - * @gran: Granularity in ns. |
---|
| 2254 | + * timestamp_truncate - Truncate timespec to a granularity |
---|
| 2255 | + * @t: Timespec |
---|
| 2256 | + * @inode: inode being updated |
---|
2131 | 2257 | * |
---|
2132 | | - * Truncate a timespec64 to a granularity. Always rounds down. gran must |
---|
| 2258 | + * Truncate a timespec to the granularity supported by the fs |
---|
| 2259 | + * containing the inode. Always rounds down. gran must |
---|
2133 | 2260 | * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns). |
---|
2134 | 2261 | */ |
---|
2135 | | -struct timespec64 timespec64_trunc(struct timespec64 t, unsigned gran) |
---|
| 2262 | +struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode) |
---|
2136 | 2263 | { |
---|
2137 | | - /* Avoid division in the common cases 1 ns and 1 s. */ |
---|
2138 | | - if (gran == 1) { |
---|
2139 | | - /* nothing */ |
---|
2140 | | - } else if (gran == NSEC_PER_SEC) { |
---|
| 2264 | + struct super_block *sb = inode->i_sb; |
---|
| 2265 | + unsigned int gran = sb->s_time_gran; |
---|
| 2266 | + |
---|
| 2267 | + t.tv_sec = clamp(t.tv_sec, sb->s_time_min, sb->s_time_max); |
---|
| 2268 | + if (unlikely(t.tv_sec == sb->s_time_max || t.tv_sec == sb->s_time_min)) |
---|
2141 | 2269 | t.tv_nsec = 0; |
---|
2142 | | - } else if (gran > 1 && gran < NSEC_PER_SEC) { |
---|
| 2270 | + |
---|
| 2271 | + /* Avoid division in the common cases 1 ns and 1 s. */ |
---|
| 2272 | + if (gran == 1) |
---|
| 2273 | + ; /* nothing */ |
---|
| 2274 | + else if (gran == NSEC_PER_SEC) |
---|
| 2275 | + t.tv_nsec = 0; |
---|
| 2276 | + else if (gran > 1 && gran < NSEC_PER_SEC) |
---|
2143 | 2277 | t.tv_nsec -= t.tv_nsec % gran; |
---|
2144 | | - } else { |
---|
2145 | | - WARN(1, "illegal file time granularity: %u", gran); |
---|
2146 | | - } |
---|
| 2278 | + else |
---|
| 2279 | + WARN(1, "invalid file time granularity: %u", gran); |
---|
2147 | 2280 | return t; |
---|
2148 | 2281 | } |
---|
2149 | | -EXPORT_SYMBOL(timespec64_trunc); |
---|
| 2282 | +EXPORT_SYMBOL_NS(timestamp_truncate, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
2150 | 2283 | |
---|
2151 | 2284 | /** |
---|
2152 | 2285 | * current_time - Return FS time |
---|
.. | .. |
---|
2160 | 2293 | */ |
---|
2161 | 2294 | struct timespec64 current_time(struct inode *inode) |
---|
2162 | 2295 | { |
---|
2163 | | - struct timespec64 now = current_kernel_time64(); |
---|
| 2296 | + struct timespec64 now; |
---|
| 2297 | + |
---|
| 2298 | + ktime_get_coarse_real_ts64(&now); |
---|
2164 | 2299 | |
---|
2165 | 2300 | if (unlikely(!inode->i_sb)) { |
---|
2166 | 2301 | WARN(1, "current_time() called with uninitialized super_block in the inode"); |
---|
2167 | 2302 | return now; |
---|
2168 | 2303 | } |
---|
2169 | 2304 | |
---|
2170 | | - return timespec64_trunc(now, inode->i_sb->s_time_gran); |
---|
| 2305 | + return timestamp_truncate(now, inode); |
---|
2171 | 2306 | } |
---|
2172 | 2307 | EXPORT_SYMBOL(current_time); |
---|
2173 | 2308 | |
---|
.. | .. |
---|
2256 | 2391 | return 0; |
---|
2257 | 2392 | } |
---|
2258 | 2393 | EXPORT_SYMBOL(vfs_ioc_fssetxattr_check); |
---|
| 2394 | + |
---|
| 2395 | +/** |
---|
| 2396 | + * in_group_or_capable - check whether caller is CAP_FSETID privileged |
---|
| 2397 | + * @inode: inode to check |
---|
| 2398 | + * @gid: the new/current gid of @inode |
---|
| 2399 | + * |
---|
| 2400 | + * Check wether @gid is in the caller's group list or if the caller is |
---|
| 2401 | + * privileged with CAP_FSETID over @inode. This can be used to determine |
---|
| 2402 | + * whether the setgid bit can be kept or must be dropped. |
---|
| 2403 | + * |
---|
| 2404 | + * Return: true if the caller is sufficiently privileged, false if not. |
---|
| 2405 | + */ |
---|
| 2406 | +bool in_group_or_capable(const struct inode *inode, kgid_t gid) |
---|
| 2407 | +{ |
---|
| 2408 | + if (in_group_p(gid)) |
---|
| 2409 | + return true; |
---|
| 2410 | + if (capable_wrt_inode_uidgid(inode, CAP_FSETID)) |
---|
| 2411 | + return true; |
---|
| 2412 | + return false; |
---|
| 2413 | +} |
---|
| 2414 | + |
---|
| 2415 | +/** |
---|
| 2416 | + * mode_strip_sgid - handle the sgid bit for non-directories |
---|
| 2417 | + * @dir: parent directory inode |
---|
| 2418 | + * @mode: mode of the file to be created in @dir |
---|
| 2419 | + * |
---|
| 2420 | + * If the @mode of the new file has both the S_ISGID and S_IXGRP bit |
---|
| 2421 | + * raised and @dir has the S_ISGID bit raised ensure that the caller is |
---|
| 2422 | + * either in the group of the parent directory or they have CAP_FSETID |
---|
| 2423 | + * in their user namespace and are privileged over the parent directory. |
---|
| 2424 | + * In all other cases, strip the S_ISGID bit from @mode. |
---|
| 2425 | + * |
---|
| 2426 | + * Return: the new mode to use for the file |
---|
| 2427 | + */ |
---|
| 2428 | +umode_t mode_strip_sgid(const struct inode *dir, umode_t mode) |
---|
| 2429 | +{ |
---|
| 2430 | + if ((mode & (S_ISGID | S_IXGRP)) != (S_ISGID | S_IXGRP)) |
---|
| 2431 | + return mode; |
---|
| 2432 | + if (S_ISDIR(mode) || !dir || !(dir->i_mode & S_ISGID)) |
---|
| 2433 | + return mode; |
---|
| 2434 | + if (in_group_or_capable(dir, dir->i_gid)) |
---|
| 2435 | + return mode; |
---|
| 2436 | + return mode & ~S_ISGID; |
---|
| 2437 | +} |
---|
| 2438 | +EXPORT_SYMBOL(mode_strip_sgid); |
---|