From 072de836f53be56a70cecf70b43ae43b7ce17376 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 10:08:36 +0000
Subject: [PATCH] mk-rootfs.sh
---
kernel/fs/configfs/dir.c | 215 ++++++++++++++++++++++-------------------------------
1 files changed, 89 insertions(+), 126 deletions(-)
diff --git a/kernel/fs/configfs/dir.c b/kernel/fs/configfs/dir.c
index 796a6cd..86bbd25 100644
--- a/kernel/fs/configfs/dir.c
+++ b/kernel/fs/configfs/dir.c
@@ -1,22 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* -*- mode: c; c-basic-offset: 8; -*-
* vim: noexpandtab sw=8 ts=8 sts=0:
*
* dir.c - Operations for configfs directories.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
*
* Based on sysfs:
* sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
@@ -27,6 +13,7 @@
#undef DEBUG
#include <linux/fs.h>
+#include <linux/fsnotify.h>
#include <linux/mount.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -35,7 +22,6 @@
#include <linux/configfs.h>
#include "configfs_internal.h"
-DECLARE_RWSEM(configfs_rename_sem);
/*
* Protects mutations of configfs_dirent linkage together with proper i_mutex
* Also protects mutations of symlinks linkage to target configfs_dirent
@@ -212,7 +198,6 @@
return ERR_PTR(-ENOMEM);
atomic_set(&sd->s_count, 1);
- INIT_LIST_HEAD(&sd->s_links);
INIT_LIST_HEAD(&sd->s_children);
sd->s_element = element;
sd->s_type = type;
@@ -274,30 +259,16 @@
return 0;
}
-static void init_dir(struct inode * inode)
+static void configfs_remove_dirent(struct dentry *dentry)
{
- inode->i_op = &configfs_dir_inode_operations;
- inode->i_fop = &configfs_dir_operations;
+ struct configfs_dirent *sd = dentry->d_fsdata;
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
- inc_nlink(inode);
-}
-
-static void configfs_init_file(struct inode * inode)
-{
- inode->i_size = PAGE_SIZE;
- inode->i_fop = &configfs_file_operations;
-}
-
-static void configfs_init_bin_file(struct inode *inode)
-{
- inode->i_size = 0;
- inode->i_fop = &configfs_bin_file_operations;
-}
-
-static void init_symlink(struct inode * inode)
-{
- inode->i_op = &configfs_symlink_inode_operations;
+ if (!sd)
+ return;
+ spin_lock(&configfs_dirent_lock);
+ list_del_init(&sd->s_sibling);
+ spin_unlock(&configfs_dirent_lock);
+ configfs_put(sd);
}
/**
@@ -315,6 +286,7 @@
int error;
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
struct dentry *p = dentry->d_parent;
+ struct inode *inode;
BUG_ON(!item);
@@ -329,20 +301,24 @@
return error;
configfs_set_dir_dirent_depth(p->d_fsdata, dentry->d_fsdata);
- error = configfs_create(dentry, mode, init_dir);
- if (!error) {
- inc_nlink(d_inode(p));
- item->ci_dentry = dentry;
- } else {
- struct configfs_dirent *sd = dentry->d_fsdata;
- if (sd) {
- spin_lock(&configfs_dirent_lock);
- list_del_init(&sd->s_sibling);
- spin_unlock(&configfs_dirent_lock);
- configfs_put(sd);
- }
- }
- return error;
+ inode = configfs_create(dentry, mode);
+ if (IS_ERR(inode))
+ goto out_remove;
+
+ inode->i_op = &configfs_dir_inode_operations;
+ inode->i_fop = &configfs_dir_operations;
+ /* directory inodes start off with i_nlink == 2 (for "." entry) */
+ inc_nlink(inode);
+ d_instantiate(dentry, inode);
+ /* already hashed */
+ dget(dentry); /* pin directory dentries in core */
+ inc_nlink(d_inode(p));
+ item->ci_dentry = dentry;
+ return 0;
+
+out_remove:
+ configfs_remove_dirent(dentry);
+ return PTR_ERR(inode);
}
/*
@@ -383,41 +359,40 @@
return ret;
}
-int configfs_create_link(struct configfs_symlink *sl,
- struct dentry *parent,
- struct dentry *dentry)
+int configfs_create_link(struct configfs_dirent *target, struct dentry *parent,
+ struct dentry *dentry, char *body)
{
int err = 0;
umode_t mode = S_IFLNK | S_IRWXUGO;
struct configfs_dirent *p = parent->d_fsdata;
+ struct inode *inode;
- err = configfs_make_dirent(p, dentry, sl, mode,
- CONFIGFS_ITEM_LINK, p->s_frag);
- if (!err) {
- err = configfs_create(dentry, mode, init_symlink);
- if (err) {
- struct configfs_dirent *sd = dentry->d_fsdata;
- if (sd) {
- spin_lock(&configfs_dirent_lock);
- list_del_init(&sd->s_sibling);
- spin_unlock(&configfs_dirent_lock);
- configfs_put(sd);
- }
- }
- }
- return err;
+ err = configfs_make_dirent(p, dentry, target, mode, CONFIGFS_ITEM_LINK,
+ p->s_frag);
+ if (err)
+ return err;
+
+ inode = configfs_create(dentry, mode);
+ if (IS_ERR(inode))
+ goto out_remove;
+
+ inode->i_link = body;
+ inode->i_op = &configfs_symlink_inode_operations;
+ d_instantiate(dentry, inode);
+ dget(dentry); /* pin link dentries in core */
+ return 0;
+
+out_remove:
+ configfs_remove_dirent(dentry);
+ return PTR_ERR(inode);
}
static void remove_dir(struct dentry * d)
{
struct dentry * parent = dget(d->d_parent);
- struct configfs_dirent * sd;
- sd = d->d_fsdata;
- spin_lock(&configfs_dirent_lock);
- list_del_init(&sd->s_sibling);
- spin_unlock(&configfs_dirent_lock);
- configfs_put(sd);
+ configfs_remove_dirent(d);
+
if (d_really_is_positive(d))
simple_rmdir(d_inode(parent),d);
@@ -458,20 +433,27 @@
static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * dentry)
{
struct configfs_attribute * attr = sd->s_element;
- int error;
+ struct inode *inode;
spin_lock(&configfs_dirent_lock);
dentry->d_fsdata = configfs_get(sd);
sd->s_dentry = dentry;
spin_unlock(&configfs_dirent_lock);
- error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
- (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) ?
- configfs_init_bin_file :
- configfs_init_file);
- if (error)
+ inode = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG);
+ if (IS_ERR(inode)) {
configfs_put(sd);
- return error;
+ return PTR_ERR(inode);
+ }
+ if (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) {
+ inode->i_size = 0;
+ inode->i_fop = &configfs_bin_file_operations;
+ } else {
+ inode->i_size = PAGE_SIZE;
+ inode->i_fop = &configfs_file_operations;
+ }
+ d_add(dentry, inode);
+ return 0;
}
static struct dentry * configfs_lookup(struct inode *dir,
@@ -541,7 +523,7 @@
parent_sd->s_type |= CONFIGFS_USET_DROPPING;
ret = -EBUSY;
- if (!list_empty(&parent_sd->s_links))
+ if (parent_sd->s_links)
goto out;
ret = 0;
@@ -1194,7 +1176,7 @@
/*
* Release the dependent linkage. This is much simpler than
- * configfs_depend_item() because we know that that the client driver is
+ * configfs_depend_item() because we know that the client driver is
* pinned, thus the subsystem is pinned, and therefore configfs is pinned.
*/
void configfs_undepend_item(struct config_item *target)
@@ -1435,6 +1417,21 @@
else
ret = configfs_attach_item(parent_item, item, dentry, frag);
+ /* inherit uid/gid from process creating the directory */
+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID) ||
+ !gid_eq(current_fsgid(), GLOBAL_ROOT_GID)) {
+ struct iattr ia = {
+ .ia_uid = current_fsuid(),
+ .ia_gid = current_fsgid(),
+ .ia_valid = ATTR_UID | ATTR_GID,
+ };
+ struct inode *inode = d_inode(dentry);
+ inode->i_uid = ia.ia_uid;
+ inode->i_gid = ia.ia_gid;
+ /* the above manual assignments skip the permission checks */
+ configfs_setattr(dentry, &ia);
+ }
+
spin_lock(&configfs_dirent_lock);
sd->s_type &= ~CONFIGFS_USET_IN_MKDIR;
if (!ret)
@@ -1600,44 +1597,6 @@
.setattr = configfs_setattr,
};
-#if 0
-int configfs_rename_dir(struct config_item * item, const char *new_name)
-{
- int error = 0;
- struct dentry * new_dentry, * parent;
-
- if (!strcmp(config_item_name(item), new_name))
- return -EINVAL;
-
- if (!item->parent)
- return -EINVAL;
-
- down_write(&configfs_rename_sem);
- parent = item->parent->dentry;
-
- inode_lock(d_inode(parent));
-
- new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
- if (!IS_ERR(new_dentry)) {
- if (d_really_is_negative(new_dentry)) {
- error = config_item_set_name(item, "%s", new_name);
- if (!error) {
- d_add(new_dentry, NULL);
- d_move(item->dentry, new_dentry);
- }
- else
- d_delete(new_dentry);
- } else
- error = -EEXIST;
- dput(new_dentry);
- }
- inode_unlock(d_inode(parent));
- up_write(&configfs_rename_sem);
-
- return error;
-}
-#endif
-
static int configfs_dir_open(struct inode *inode, struct file *file)
{
struct dentry * dentry = file->f_path.dentry;
@@ -1752,9 +1711,11 @@
switch (whence) {
case 1:
offset += file->f_pos;
+ fallthrough;
case 0:
if (offset >= 0)
break;
+ fallthrough;
default:
return -EINVAL;
}
@@ -1867,7 +1828,8 @@
configfs_detach_group(&group->cg_item);
d_inode(dentry)->i_flags |= S_DEAD;
dont_mount(dentry);
- d_delete(dentry);
+ d_drop(dentry);
+ fsnotify_rmdir(d_inode(parent), dentry);
inode_unlock(d_inode(parent));
dput(dentry);
@@ -2014,7 +1976,8 @@
dont_mount(dentry);
inode_unlock(d_inode(dentry));
- d_delete(dentry);
+ d_drop(dentry);
+ fsnotify_rmdir(d_inode(root), dentry);
inode_unlock(d_inode(root));
--
Gitblit v1.6.2