hc
2024-10-09 05e59e5fb0064c97a1c10921ecd549f2d4a58565
kernel/fs/configfs/dir.c
....@@ -1,22 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* -*- mode: c; c-basic-offset: 8; -*-
23 * vim: noexpandtab sw=8 ts=8 sts=0:
34 *
45 * dir.c - Operations for configfs directories.
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public
8
- * License as published by the Free Software Foundation; either
9
- * version 2 of the License, or (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
- * General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public
17
- * License along with this program; if not, write to the
18
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
- * Boston, MA 021110-1307, USA.
206 *
217 * Based on sysfs:
228 * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
....@@ -27,6 +13,7 @@
2713 #undef DEBUG
2814
2915 #include <linux/fs.h>
16
+#include <linux/fsnotify.h>
3017 #include <linux/mount.h>
3118 #include <linux/module.h>
3219 #include <linux/slab.h>
....@@ -35,7 +22,6 @@
3522 #include <linux/configfs.h>
3623 #include "configfs_internal.h"
3724
38
-DECLARE_RWSEM(configfs_rename_sem);
3925 /*
4026 * Protects mutations of configfs_dirent linkage together with proper i_mutex
4127 * Also protects mutations of symlinks linkage to target configfs_dirent
....@@ -212,7 +198,6 @@
212198 return ERR_PTR(-ENOMEM);
213199
214200 atomic_set(&sd->s_count, 1);
215
- INIT_LIST_HEAD(&sd->s_links);
216201 INIT_LIST_HEAD(&sd->s_children);
217202 sd->s_element = element;
218203 sd->s_type = type;
....@@ -274,30 +259,16 @@
274259 return 0;
275260 }
276261
277
-static void init_dir(struct inode * inode)
262
+static void configfs_remove_dirent(struct dentry *dentry)
278263 {
279
- inode->i_op = &configfs_dir_inode_operations;
280
- inode->i_fop = &configfs_dir_operations;
264
+ struct configfs_dirent *sd = dentry->d_fsdata;
281265
282
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
283
- inc_nlink(inode);
284
-}
285
-
286
-static void configfs_init_file(struct inode * inode)
287
-{
288
- inode->i_size = PAGE_SIZE;
289
- inode->i_fop = &configfs_file_operations;
290
-}
291
-
292
-static void configfs_init_bin_file(struct inode *inode)
293
-{
294
- inode->i_size = 0;
295
- inode->i_fop = &configfs_bin_file_operations;
296
-}
297
-
298
-static void init_symlink(struct inode * inode)
299
-{
300
- inode->i_op = &configfs_symlink_inode_operations;
266
+ if (!sd)
267
+ return;
268
+ spin_lock(&configfs_dirent_lock);
269
+ list_del_init(&sd->s_sibling);
270
+ spin_unlock(&configfs_dirent_lock);
271
+ configfs_put(sd);
301272 }
302273
303274 /**
....@@ -315,6 +286,7 @@
315286 int error;
316287 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
317288 struct dentry *p = dentry->d_parent;
289
+ struct inode *inode;
318290
319291 BUG_ON(!item);
320292
....@@ -329,20 +301,25 @@
329301 return error;
330302
331303 configfs_set_dir_dirent_depth(p->d_fsdata, dentry->d_fsdata);
332
- error = configfs_create(dentry, mode, init_dir);
333
- if (!error) {
334
- inc_nlink(d_inode(p));
335
- item->ci_dentry = dentry;
336
- } else {
337
- struct configfs_dirent *sd = dentry->d_fsdata;
338
- if (sd) {
339
- spin_lock(&configfs_dirent_lock);
340
- list_del_init(&sd->s_sibling);
341
- spin_unlock(&configfs_dirent_lock);
342
- configfs_put(sd);
343
- }
344
- }
345
- return error;
304
+ inode = configfs_create(dentry, mode);
305
+ if (IS_ERR(inode))
306
+ goto out_remove;
307
+
308
+ inode->i_op = &configfs_dir_inode_operations;
309
+ inode->i_fop = &configfs_dir_operations;
310
+ /* directory inodes start off with i_nlink == 2 (for "." entry) */
311
+ inc_nlink(inode);
312
+ d_instantiate(dentry, inode);
313
+ /* already hashed */
314
+ dget(dentry); /* pin directory dentries in core */
315
+ inc_nlink(d_inode(p));
316
+ item->ci_dentry = dentry;
317
+ return 0;
318
+
319
+out_remove:
320
+ configfs_put(dentry->d_fsdata);
321
+ configfs_remove_dirent(dentry);
322
+ return PTR_ERR(inode);
346323 }
347324
348325 /*
....@@ -383,41 +360,41 @@
383360 return ret;
384361 }
385362
386
-int configfs_create_link(struct configfs_symlink *sl,
387
- struct dentry *parent,
388
- struct dentry *dentry)
363
+int configfs_create_link(struct configfs_dirent *target, struct dentry *parent,
364
+ struct dentry *dentry, char *body)
389365 {
390366 int err = 0;
391367 umode_t mode = S_IFLNK | S_IRWXUGO;
392368 struct configfs_dirent *p = parent->d_fsdata;
369
+ struct inode *inode;
393370
394
- err = configfs_make_dirent(p, dentry, sl, mode,
395
- CONFIGFS_ITEM_LINK, p->s_frag);
396
- if (!err) {
397
- err = configfs_create(dentry, mode, init_symlink);
398
- if (err) {
399
- struct configfs_dirent *sd = dentry->d_fsdata;
400
- if (sd) {
401
- spin_lock(&configfs_dirent_lock);
402
- list_del_init(&sd->s_sibling);
403
- spin_unlock(&configfs_dirent_lock);
404
- configfs_put(sd);
405
- }
406
- }
407
- }
408
- return err;
371
+ err = configfs_make_dirent(p, dentry, target, mode, CONFIGFS_ITEM_LINK,
372
+ p->s_frag);
373
+ if (err)
374
+ return err;
375
+
376
+ inode = configfs_create(dentry, mode);
377
+ if (IS_ERR(inode))
378
+ goto out_remove;
379
+
380
+ inode->i_link = body;
381
+ inode->i_op = &configfs_symlink_inode_operations;
382
+ d_instantiate(dentry, inode);
383
+ dget(dentry); /* pin link dentries in core */
384
+ return 0;
385
+
386
+out_remove:
387
+ configfs_put(dentry->d_fsdata);
388
+ configfs_remove_dirent(dentry);
389
+ return PTR_ERR(inode);
409390 }
410391
411392 static void remove_dir(struct dentry * d)
412393 {
413394 struct dentry * parent = dget(d->d_parent);
414
- struct configfs_dirent * sd;
415395
416
- sd = d->d_fsdata;
417
- spin_lock(&configfs_dirent_lock);
418
- list_del_init(&sd->s_sibling);
419
- spin_unlock(&configfs_dirent_lock);
420
- configfs_put(sd);
396
+ configfs_remove_dirent(d);
397
+
421398 if (d_really_is_positive(d))
422399 simple_rmdir(d_inode(parent),d);
423400
....@@ -458,20 +435,27 @@
458435 static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * dentry)
459436 {
460437 struct configfs_attribute * attr = sd->s_element;
461
- int error;
438
+ struct inode *inode;
462439
463440 spin_lock(&configfs_dirent_lock);
464441 dentry->d_fsdata = configfs_get(sd);
465442 sd->s_dentry = dentry;
466443 spin_unlock(&configfs_dirent_lock);
467444
468
- error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
469
- (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) ?
470
- configfs_init_bin_file :
471
- configfs_init_file);
472
- if (error)
445
+ inode = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG);
446
+ if (IS_ERR(inode)) {
473447 configfs_put(sd);
474
- return error;
448
+ return PTR_ERR(inode);
449
+ }
450
+ if (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) {
451
+ inode->i_size = 0;
452
+ inode->i_fop = &configfs_bin_file_operations;
453
+ } else {
454
+ inode->i_size = PAGE_SIZE;
455
+ inode->i_fop = &configfs_file_operations;
456
+ }
457
+ d_add(dentry, inode);
458
+ return 0;
475459 }
476460
477461 static struct dentry * configfs_lookup(struct inode *dir,
....@@ -541,7 +525,7 @@
541525 parent_sd->s_type |= CONFIGFS_USET_DROPPING;
542526
543527 ret = -EBUSY;
544
- if (!list_empty(&parent_sd->s_links))
528
+ if (parent_sd->s_links)
545529 goto out;
546530
547531 ret = 0;
....@@ -1194,7 +1178,7 @@
11941178
11951179 /*
11961180 * Release the dependent linkage. This is much simpler than
1197
- * configfs_depend_item() because we know that that the client driver is
1181
+ * configfs_depend_item() because we know that the client driver is
11981182 * pinned, thus the subsystem is pinned, and therefore configfs is pinned.
11991183 */
12001184 void configfs_undepend_item(struct config_item *target)
....@@ -1435,6 +1419,21 @@
14351419 else
14361420 ret = configfs_attach_item(parent_item, item, dentry, frag);
14371421
1422
+ /* inherit uid/gid from process creating the directory */
1423
+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID) ||
1424
+ !gid_eq(current_fsgid(), GLOBAL_ROOT_GID)) {
1425
+ struct iattr ia = {
1426
+ .ia_uid = current_fsuid(),
1427
+ .ia_gid = current_fsgid(),
1428
+ .ia_valid = ATTR_UID | ATTR_GID,
1429
+ };
1430
+ struct inode *inode = d_inode(dentry);
1431
+ inode->i_uid = ia.ia_uid;
1432
+ inode->i_gid = ia.ia_gid;
1433
+ /* the above manual assignments skip the permission checks */
1434
+ configfs_setattr(dentry, &ia);
1435
+ }
1436
+
14381437 spin_lock(&configfs_dirent_lock);
14391438 sd->s_type &= ~CONFIGFS_USET_IN_MKDIR;
14401439 if (!ret)
....@@ -1600,44 +1599,6 @@
16001599 .setattr = configfs_setattr,
16011600 };
16021601
1603
-#if 0
1604
-int configfs_rename_dir(struct config_item * item, const char *new_name)
1605
-{
1606
- int error = 0;
1607
- struct dentry * new_dentry, * parent;
1608
-
1609
- if (!strcmp(config_item_name(item), new_name))
1610
- return -EINVAL;
1611
-
1612
- if (!item->parent)
1613
- return -EINVAL;
1614
-
1615
- down_write(&configfs_rename_sem);
1616
- parent = item->parent->dentry;
1617
-
1618
- inode_lock(d_inode(parent));
1619
-
1620
- new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
1621
- if (!IS_ERR(new_dentry)) {
1622
- if (d_really_is_negative(new_dentry)) {
1623
- error = config_item_set_name(item, "%s", new_name);
1624
- if (!error) {
1625
- d_add(new_dentry, NULL);
1626
- d_move(item->dentry, new_dentry);
1627
- }
1628
- else
1629
- d_delete(new_dentry);
1630
- } else
1631
- error = -EEXIST;
1632
- dput(new_dentry);
1633
- }
1634
- inode_unlock(d_inode(parent));
1635
- up_write(&configfs_rename_sem);
1636
-
1637
- return error;
1638
-}
1639
-#endif
1640
-
16411602 static int configfs_dir_open(struct inode *inode, struct file *file)
16421603 {
16431604 struct dentry * dentry = file->f_path.dentry;
....@@ -1752,9 +1713,11 @@
17521713 switch (whence) {
17531714 case 1:
17541715 offset += file->f_pos;
1716
+ fallthrough;
17551717 case 0:
17561718 if (offset >= 0)
17571719 break;
1720
+ fallthrough;
17581721 default:
17591722 return -EINVAL;
17601723 }
....@@ -1867,7 +1830,8 @@
18671830 configfs_detach_group(&group->cg_item);
18681831 d_inode(dentry)->i_flags |= S_DEAD;
18691832 dont_mount(dentry);
1870
- d_delete(dentry);
1833
+ d_drop(dentry);
1834
+ fsnotify_rmdir(d_inode(parent), dentry);
18711835 inode_unlock(d_inode(parent));
18721836
18731837 dput(dentry);
....@@ -2014,7 +1978,8 @@
20141978 dont_mount(dentry);
20151979 inode_unlock(d_inode(dentry));
20161980
2017
- d_delete(dentry);
1981
+ d_drop(dentry);
1982
+ fsnotify_rmdir(d_inode(root), dentry);
20181983
20191984 inode_unlock(d_inode(root));
20201985