Unverified Commit bb57289f authored by Christian Brauner's avatar Christian Brauner
Browse files

Merge patch series "ns: rework common initialization"

Christian Brauner <brauner@kernel.org> says:

The current scheme still involves a lot of open-coding and copy-pasing
and bleeds a lot of unnecessary details into actual namespace
implementers. Encapsulate it in the common helpers and simplify it all.

* patches from https://lore.kernel.org/20250917-work-namespace-ns_common-v1-0-1b3bda8ef8f2@kernel.org

:
  ns: add ns_common_free()
  nscommon: simplify initialization
  net: centralize ns_common initialization
  mnt: simplify ns_common_init() handling
  nsfs: add inode number for anon namespace
  cgroup: split namespace into separate header
  nscommon: move to separate file
  mnt: expose pointer to init_mnt_ns
  uts: split namespace into separate header

Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parents 3ab378cf be5f21d3
Loading
Loading
Loading
Loading
+22 −14
Original line number Diff line number Diff line
@@ -4082,7 +4082,7 @@ static void dec_mnt_namespaces(struct ucounts *ucounts)
static void free_mnt_ns(struct mnt_namespace *ns)
{
	if (!is_anon_ns(ns))
		ns_free_inum(&ns->ns);
		ns_common_free(ns);
	dec_mnt_namespaces(ns->ucounts);
	mnt_ns_tree_remove(ns);
}
@@ -4103,7 +4103,10 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns, bool a
		return ERR_PTR(-ENOMEM);
	}

	ret = ns_common_init(&new_ns->ns, &mntns_operations, !anon);
	if (anon)
		ret = ns_common_init_inum(new_ns, &mntns_operations, MNT_NS_ANON_INO);
	else
		ret = ns_common_init(new_ns, &mntns_operations);
	if (ret) {
		kfree(new_ns);
		dec_mnt_namespaces(ucounts);
@@ -4151,7 +4154,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
	if (IS_ERR(new)) {
		namespace_unlock();
		ns_free_inum(&new_ns->ns);
		ns_common_free(ns);
		dec_mnt_namespaces(new_ns->ucounts);
		mnt_ns_release(new_ns);
		return ERR_CAST(new);
@@ -6008,27 +6011,32 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
	return ret;
}

struct mnt_namespace init_mnt_ns = {
	.ns.inum	= PROC_MNT_INIT_INO,
	.ns.ops		= &mntns_operations,
	.user_ns	= &init_user_ns,
	.ns.count	= REFCOUNT_INIT(1),
	.passive	= REFCOUNT_INIT(1),
	.mounts		= RB_ROOT,
	.poll		= __WAIT_QUEUE_HEAD_INITIALIZER(init_mnt_ns.poll),
};

static void __init init_mount_tree(void)
{
	struct vfsmount *mnt;
	struct mount *m;
	struct mnt_namespace *ns;
	struct path root;

	mnt = vfs_kern_mount(&rootfs_fs_type, 0, "rootfs", NULL);
	if (IS_ERR(mnt))
		panic("Can't create rootfs");

	ns = alloc_mnt_ns(&init_user_ns, true);
	if (IS_ERR(ns))
		panic("Can't allocate initial namespace");
	ns->ns.inum = PROC_MNT_INIT_INO;
	m = real_mount(mnt);
	ns->root = m;
	ns->nr_mounts = 1;
	mnt_add_to_ns(ns, m);
	init_task.nsproxy->mnt_ns = ns;
	get_mnt_ns(ns);
	init_mnt_ns.root = m;
	init_mnt_ns.nr_mounts = 1;
	mnt_add_to_ns(&init_mnt_ns, m);
	init_task.nsproxy->mnt_ns = &init_mnt_ns;
	get_mnt_ns(&init_mnt_ns);

	root.mnt = mnt;
	root.dentry = mnt->mnt_root;
@@ -6036,7 +6044,7 @@ static void __init init_mount_tree(void)
	set_fs_pwd(current->fs, &root);
	set_fs_root(current->fs, &root);

	ns_tree_add(ns);
	ns_tree_add(&init_mnt_ns);
}

void __init mnt_init(void)
+1 −50
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/kernel_stat.h>

#include <linux/cgroup-defs.h>
#include <linux/cgroup_namespace.h>

struct kernel_clone_args;

@@ -783,56 +784,6 @@ static inline void cgroup_sk_free(struct sock_cgroup_data *skcd) {}

#endif	/* CONFIG_CGROUP_DATA */

struct cgroup_namespace {
	struct ns_common	ns;
	struct user_namespace	*user_ns;
	struct ucounts		*ucounts;
	struct css_set          *root_cset;
};

extern struct cgroup_namespace init_cgroup_ns;

#ifdef CONFIG_CGROUPS

static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns)
{
	return container_of(ns, struct cgroup_namespace, ns);
}

void free_cgroup_ns(struct cgroup_namespace *ns);

struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
					struct user_namespace *user_ns,
					struct cgroup_namespace *old_ns);

int cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
		   struct cgroup_namespace *ns);

static inline void get_cgroup_ns(struct cgroup_namespace *ns)
{
	refcount_inc(&ns->ns.count);
}

static inline void put_cgroup_ns(struct cgroup_namespace *ns)
{
	if (refcount_dec_and_test(&ns->ns.count))
		free_cgroup_ns(ns);
}

#else /* !CONFIG_CGROUPS */

static inline void free_cgroup_ns(struct cgroup_namespace *ns) { }
static inline struct cgroup_namespace *
copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns,
	       struct cgroup_namespace *old_ns)
{
	return old_ns;
}

static inline void get_cgroup_ns(struct cgroup_namespace *ns) { }
static inline void put_cgroup_ns(struct cgroup_namespace *ns) { }

#endif /* !CONFIG_CGROUPS */

#ifdef CONFIG_CGROUPS

+56 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_CGROUP_NAMESPACE_H
#define _LINUX_CGROUP_NAMESPACE_H

struct cgroup_namespace {
	struct ns_common	ns;
	struct user_namespace	*user_ns;
	struct ucounts		*ucounts;
	struct css_set          *root_cset;
};

extern struct cgroup_namespace init_cgroup_ns;

#ifdef CONFIG_CGROUPS

static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns)
{
	return container_of(ns, struct cgroup_namespace, ns);
}

void free_cgroup_ns(struct cgroup_namespace *ns);

struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
					struct user_namespace *user_ns,
					struct cgroup_namespace *old_ns);

int cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
		   struct cgroup_namespace *ns);

static inline void get_cgroup_ns(struct cgroup_namespace *ns)
{
	refcount_inc(&ns->ns.count);
}

static inline void put_cgroup_ns(struct cgroup_namespace *ns)
{
	if (refcount_dec_and_test(&ns->ns.count))
		free_cgroup_ns(ns);
}

#else /* !CONFIG_CGROUPS */

static inline void free_cgroup_ns(struct cgroup_namespace *ns) { }
static inline struct cgroup_namespace *
copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns,
	       struct cgroup_namespace *old_ns)
{
	return old_ns;
}

static inline void get_cgroup_ns(struct cgroup_namespace *ns) { }
static inline void put_cgroup_ns(struct cgroup_namespace *ns) { }

#endif /* !CONFIG_CGROUPS */

#endif /* _LINUX_CGROUP_NAMESPACE_H */
+2 −0
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@ struct fs_struct;
struct user_namespace;
struct ns_common;

extern struct mnt_namespace init_mnt_ns;

extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
		struct user_namespace *, struct fs_struct *);
extern void put_mnt_ns(struct mnt_namespace *ns);
+41 −0
Original line number Diff line number Diff line
@@ -16,6 +16,15 @@ struct time_namespace;
struct user_namespace;
struct uts_namespace;

extern struct cgroup_namespace init_cgroup_ns;
extern struct ipc_namespace init_ipc_ns;
extern struct mnt_namespace init_mnt_ns;
extern struct net init_net;
extern struct pid_namespace init_pid_ns;
extern struct time_namespace init_time_ns;
extern struct user_namespace init_user_ns;
extern struct uts_namespace init_uts_ns;

struct ns_common {
	struct dentry *stashed;
	const struct proc_ns_operations *ops;
@@ -31,6 +40,9 @@ struct ns_common {
	};
};

int __ns_common_init(struct ns_common *ns, const struct proc_ns_operations *ops, int inum);
void __ns_common_free(struct ns_common *ns);

#define to_ns_common(__ns)                              \
	_Generic((__ns),                                \
		struct cgroup_namespace *: &(__ns)->ns, \
@@ -42,4 +54,33 @@ struct ns_common {
		struct user_namespace *:   &(__ns)->ns, \
		struct uts_namespace *:    &(__ns)->ns)

#define ns_init_inum(__ns)                                     \
	_Generic((__ns),                                       \
		struct cgroup_namespace *: CGROUP_NS_INIT_INO, \
		struct ipc_namespace *:    IPC_NS_INIT_INO,    \
		struct mnt_namespace *:    MNT_NS_INIT_INO,    \
		struct net *:              NET_NS_INIT_INO,    \
		struct pid_namespace *:    PID_NS_INIT_INO,    \
		struct time_namespace *:   TIME_NS_INIT_INO,   \
		struct user_namespace *:   USER_NS_INIT_INO,   \
		struct uts_namespace *:    UTS_NS_INIT_INO)

#define ns_init_ns(__ns)                                    \
	_Generic((__ns),                                    \
		struct cgroup_namespace *: &init_cgroup_ns, \
		struct ipc_namespace *:    &init_ipc_ns,    \
		struct mnt_namespace *:    &init_mnt_ns,     \
		struct net *:              &init_net,       \
		struct pid_namespace *:    &init_pid_ns,    \
		struct time_namespace *:   &init_time_ns,   \
		struct user_namespace *:   &init_user_ns,   \
		struct uts_namespace *:    &init_uts_ns)

#define ns_common_init(__ns, __ops) \
	__ns_common_init(to_ns_common(__ns), __ops, (((__ns) == ns_init_ns(__ns)) ? ns_init_inum(__ns) : 0))

#define ns_common_init_inum(__ns, __ops, __inum) __ns_common_init(to_ns_common(__ns), __ops, __inum)

#define ns_common_free(__ns) __ns_common_free(to_ns_common((__ns)))

#endif
Loading