kernfs: pass struct ns_common instead of const void * for namespace tags

kernfs has historically used const void * to pass around namespace tags
used for directory-level namespace filtering. The only current user of
this is sysfs network namespace tagging where struct net pointers are
cast to void *.

Replace all const void * namespace parameters with const struct
ns_common * throughout the kernfs, sysfs, and kobject namespace layers.
This includes the kobj_ns_type_operations callbacks, kobject_namespace(),
and all sysfs/kernfs APIs that accept or return namespace tags.

Passing struct ns_common is needed because various codepaths require
access to the underlying namespace. A struct ns_common can always be
converted back to the concrete namespace type (e.g., struct net) via
container_of() or to_ns_common() in the reverse direction.

This is a preparatory change for switching to ns_id-based directory
iteration to prevent a KASLR pointer leak through the current use of
raw namespace pointers as hash seeds and comparison keys.

Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Christian Brauner
2026-04-01 12:15:58 +02:00
parent 07712db808
commit e3b2cf6e5d
30 changed files with 175 additions and 148 deletions

View File

@@ -37,7 +37,7 @@ void sysfs_warn_dup(struct kernfs_node *parent, const char *name)
* @kobj: object we're creating directory for
* @ns: the namespace tag to use
*/
int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
int sysfs_create_dir_ns(struct kobject *kobj, const struct ns_common *ns)
{
struct kernfs_node *parent, *kn;
kuid_t uid;
@@ -103,7 +103,7 @@ void sysfs_remove_dir(struct kobject *kobj)
}
int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
const void *new_ns)
const struct ns_common *new_ns)
{
struct kernfs_node *parent;
int ret;
@@ -115,7 +115,7 @@ int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
}
int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
const void *new_ns)
const struct ns_common *new_ns)
{
struct kernfs_node *kn = kobj->sd;
struct kernfs_node *new_parent;

View File

@@ -272,7 +272,7 @@ static const struct kernfs_ops sysfs_bin_kfops_mmap = {
int sysfs_add_file_mode_ns(struct kernfs_node *parent,
const struct attribute *attr, umode_t mode, kuid_t uid,
kgid_t gid, const void *ns)
kgid_t gid, const struct ns_common *ns)
{
struct kobject *kobj = parent->priv;
const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops;
@@ -322,7 +322,7 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent,
int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
const struct bin_attribute *battr, umode_t mode, size_t size,
kuid_t uid, kgid_t gid, const void *ns)
kuid_t uid, kgid_t gid, const struct ns_common *ns)
{
const struct attribute *attr = &battr->attr;
struct lock_class_key *key = NULL;
@@ -362,7 +362,7 @@ int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
* @ns: namespace the new file should belong to
*/
int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
const void *ns)
const struct ns_common *ns)
{
kuid_t uid;
kgid_t gid;
@@ -505,7 +505,7 @@ EXPORT_SYMBOL_GPL(sysfs_unbreak_active_protection);
* Hash the attribute name and namespace tag and kill the victim.
*/
void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
const void *ns)
const struct ns_common *ns)
{
struct kernfs_node *parent = kobj->sd;

View File

@@ -55,7 +55,7 @@ static const struct fs_context_operations sysfs_fs_context_ops = {
static int sysfs_init_fs_context(struct fs_context *fc)
{
struct kernfs_fs_context *kfc;
struct net *netns;
struct ns_common *ns;
if (!(fc->sb_flags & SB_KERNMOUNT)) {
if (!kobj_ns_current_may_mount(KOBJ_NS_TYPE_NET))
@@ -66,12 +66,14 @@ static int sysfs_init_fs_context(struct fs_context *fc)
if (!kfc)
return -ENOMEM;
kfc->ns_tag = netns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
kfc->ns_tag = ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
kfc->root = sysfs_root;
kfc->magic = SYSFS_MAGIC;
fc->fs_private = kfc;
fc->ops = &sysfs_fs_context_ops;
if (netns) {
if (ns) {
struct net *netns = to_net_ns(ns);
put_user_ns(fc->user_ns);
fc->user_ns = get_user_ns(netns->user_ns);
}
@@ -81,7 +83,7 @@ static int sysfs_init_fs_context(struct fs_context *fc)
static void sysfs_kill_sb(struct super_block *sb)
{
void *ns = (void *)kernfs_super_ns(sb);
struct ns_common *ns = (struct ns_common *)kernfs_super_ns(sb);
kernfs_kill_sb(sb);
kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);

View File

@@ -121,7 +121,7 @@ EXPORT_SYMBOL_GPL(sysfs_create_link_nowarn);
void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
const char *name)
{
const void *ns = NULL;
const struct ns_common *ns = NULL;
/*
* We don't own @target and it may be removed at any time.
@@ -164,10 +164,11 @@ EXPORT_SYMBOL_GPL(sysfs_remove_link);
* A helper function for the common rename symlink idiom.
*/
int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
const char *old, const char *new, const void *new_ns)
const char *old, const char *new,
const struct ns_common *new_ns)
{
struct kernfs_node *parent, *kn = NULL;
const void *old_ns = NULL;
const struct ns_common *old_ns = NULL;
int result;
if (!kobj)

View File

@@ -29,10 +29,10 @@ void sysfs_warn_dup(struct kernfs_node *parent, const char *name);
*/
int sysfs_add_file_mode_ns(struct kernfs_node *parent,
const struct attribute *attr, umode_t amode, kuid_t uid,
kgid_t gid, const void *ns);
kgid_t gid, const struct ns_common *ns);
int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
const struct bin_attribute *battr, umode_t mode, size_t size,
kuid_t uid, kgid_t gid, const void *ns);
kuid_t uid, kgid_t gid, const struct ns_common *ns);
/*
* symlink.c