mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-14 11:11:22 -04:00
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: Christian Brauner <brauner@kernel.org>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
include/linux/cgroup_namespace.h
Normal file
56
include/linux/cgroup_namespace.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* 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 */
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -66,27 +66,6 @@ static inline void proc_free_inum(unsigned int inum) {}
|
||||
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
static inline int ns_common_init(struct ns_common *ns,
|
||||
const struct proc_ns_operations *ops,
|
||||
bool alloc_inum)
|
||||
{
|
||||
if (alloc_inum) {
|
||||
int ret;
|
||||
ret = proc_alloc_inum(&ns->inum);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
refcount_set(&ns->count, 1);
|
||||
ns->stashed = NULL;
|
||||
ns->ops = ops;
|
||||
ns->ns_id = 0;
|
||||
RB_CLEAR_NODE(&ns->ns_tree_node);
|
||||
INIT_LIST_HEAD(&ns->ns_list_node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ns_free_inum(ns) proc_free_inum((ns)->inum)
|
||||
|
||||
#define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private)
|
||||
|
||||
#endif /* _LINUX_PROC_NS_H */
|
||||
|
||||
65
include/linux/uts_namespace.h
Normal file
65
include/linux/uts_namespace.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_UTS_NAMESPACE_H
|
||||
#define _LINUX_UTS_NAMESPACE_H
|
||||
|
||||
#include <linux/ns_common.h>
|
||||
#include <uapi/linux/utsname.h>
|
||||
|
||||
struct user_namespace;
|
||||
extern struct user_namespace init_user_ns;
|
||||
|
||||
struct uts_namespace {
|
||||
struct new_utsname name;
|
||||
struct user_namespace *user_ns;
|
||||
struct ucounts *ucounts;
|
||||
struct ns_common ns;
|
||||
} __randomize_layout;
|
||||
|
||||
extern struct uts_namespace init_uts_ns;
|
||||
|
||||
#ifdef CONFIG_UTS_NS
|
||||
static inline struct uts_namespace *to_uts_ns(struct ns_common *ns)
|
||||
{
|
||||
return container_of(ns, struct uts_namespace, ns);
|
||||
}
|
||||
|
||||
static inline void get_uts_ns(struct uts_namespace *ns)
|
||||
{
|
||||
refcount_inc(&ns->ns.count);
|
||||
}
|
||||
|
||||
extern struct uts_namespace *copy_utsname(unsigned long flags,
|
||||
struct user_namespace *user_ns, struct uts_namespace *old_ns);
|
||||
extern void free_uts_ns(struct uts_namespace *ns);
|
||||
|
||||
static inline void put_uts_ns(struct uts_namespace *ns)
|
||||
{
|
||||
if (refcount_dec_and_test(&ns->ns.count))
|
||||
free_uts_ns(ns);
|
||||
}
|
||||
|
||||
void uts_ns_init(void);
|
||||
#else
|
||||
static inline void get_uts_ns(struct uts_namespace *ns)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void put_uts_ns(struct uts_namespace *ns)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct uts_namespace *copy_utsname(unsigned long flags,
|
||||
struct user_namespace *user_ns, struct uts_namespace *old_ns)
|
||||
{
|
||||
if (flags & CLONE_NEWUTS)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return old_ns;
|
||||
}
|
||||
|
||||
static inline void uts_ns_init(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_UTS_NAMESPACE_H */
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/ns_common.h>
|
||||
#include <linux/err.h>
|
||||
#include <uapi/linux/utsname.h>
|
||||
#include <linux/uts_namespace.h>
|
||||
|
||||
enum uts_proc {
|
||||
UTS_PROC_ARCH,
|
||||
@@ -18,62 +18,6 @@ enum uts_proc {
|
||||
UTS_PROC_DOMAINNAME,
|
||||
};
|
||||
|
||||
struct user_namespace;
|
||||
extern struct user_namespace init_user_ns;
|
||||
|
||||
struct uts_namespace {
|
||||
struct new_utsname name;
|
||||
struct user_namespace *user_ns;
|
||||
struct ucounts *ucounts;
|
||||
struct ns_common ns;
|
||||
} __randomize_layout;
|
||||
extern struct uts_namespace init_uts_ns;
|
||||
|
||||
#ifdef CONFIG_UTS_NS
|
||||
static inline struct uts_namespace *to_uts_ns(struct ns_common *ns)
|
||||
{
|
||||
return container_of(ns, struct uts_namespace, ns);
|
||||
}
|
||||
|
||||
static inline void get_uts_ns(struct uts_namespace *ns)
|
||||
{
|
||||
refcount_inc(&ns->ns.count);
|
||||
}
|
||||
|
||||
extern struct uts_namespace *copy_utsname(unsigned long flags,
|
||||
struct user_namespace *user_ns, struct uts_namespace *old_ns);
|
||||
extern void free_uts_ns(struct uts_namespace *ns);
|
||||
|
||||
static inline void put_uts_ns(struct uts_namespace *ns)
|
||||
{
|
||||
if (refcount_dec_and_test(&ns->ns.count))
|
||||
free_uts_ns(ns);
|
||||
}
|
||||
|
||||
void uts_ns_init(void);
|
||||
#else
|
||||
static inline void get_uts_ns(struct uts_namespace *ns)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void put_uts_ns(struct uts_namespace *ns)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct uts_namespace *copy_utsname(unsigned long flags,
|
||||
struct user_namespace *user_ns, struct uts_namespace *old_ns)
|
||||
{
|
||||
if (flags & CLONE_NEWUTS)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return old_ns;
|
||||
}
|
||||
|
||||
static inline void uts_ns_init(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PROC_SYSCTL
|
||||
extern void uts_proc_notify(enum uts_proc proc);
|
||||
#else
|
||||
|
||||
@@ -53,6 +53,9 @@ enum init_ns_ino {
|
||||
TIME_NS_INIT_INO = 0xEFFFFFFAU,
|
||||
NET_NS_INIT_INO = 0xEFFFFFF9U,
|
||||
MNT_NS_INIT_INO = 0xEFFFFFF8U,
|
||||
#ifdef __KERNEL__
|
||||
MNT_NS_ANON_INO = 0xEFFFFFF7U,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct nsfs_file_handle {
|
||||
|
||||
@@ -62,7 +62,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
|
||||
if (ns == NULL)
|
||||
goto fail_dec;
|
||||
|
||||
err = ns_common_init(&ns->ns, &ipcns_operations, true);
|
||||
err = ns_common_init(ns, &ipcns_operations);
|
||||
if (err)
|
||||
goto fail_free;
|
||||
|
||||
@@ -97,7 +97,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
|
||||
|
||||
fail_put:
|
||||
put_user_ns(ns->user_ns);
|
||||
ns_free_inum(&ns->ns);
|
||||
ns_common_free(ns);
|
||||
fail_free:
|
||||
kfree(ns);
|
||||
fail_dec:
|
||||
@@ -161,7 +161,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
|
||||
|
||||
dec_ipc_namespaces(ns->ucounts);
|
||||
put_user_ns(ns->user_ns);
|
||||
ns_free_inum(&ns->ns);
|
||||
ns_common_free(ns);
|
||||
kfree(ns);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ obj-y = fork.o exec_domain.o panic.o \
|
||||
sysctl.o capability.o ptrace.o user.o \
|
||||
signal.o sys.o umh.o workqueue.o pid.o task_work.o \
|
||||
extable.o params.o \
|
||||
kthread.o sys_ni.o nsproxy.o nstree.o \
|
||||
kthread.o sys_ni.o nsproxy.o nstree.o nscommon.o \
|
||||
notifier.o ksysfs.o cred.o reboot.o \
|
||||
async.o range.o smpboot.o ucount.o regset.o ksyms_common.o
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ static struct cgroup_namespace *alloc_cgroup_ns(void)
|
||||
new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL_ACCOUNT);
|
||||
if (!new_ns)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ret = ns_common_init(&new_ns->ns, &cgroupns_operations, true);
|
||||
ret = ns_common_init(new_ns, &cgroupns_operations);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
ns_tree_add(new_ns);
|
||||
@@ -40,7 +40,7 @@ void free_cgroup_ns(struct cgroup_namespace *ns)
|
||||
put_css_set(ns->root_cset);
|
||||
dec_cgroup_namespaces(ns->ucounts);
|
||||
put_user_ns(ns->user_ns);
|
||||
ns_free_inum(&ns->ns);
|
||||
ns_common_free(ns);
|
||||
/* Concurrent nstree traversal depends on a grace period. */
|
||||
kfree_rcu(ns, ns.ns_rcu);
|
||||
}
|
||||
|
||||
25
kernel/nscommon.c
Normal file
25
kernel/nscommon.c
Normal file
@@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/ns_common.h>
|
||||
#include <linux/proc_ns.h>
|
||||
|
||||
int __ns_common_init(struct ns_common *ns, const struct proc_ns_operations *ops, int inum)
|
||||
{
|
||||
refcount_set(&ns->count, 1);
|
||||
ns->stashed = NULL;
|
||||
ns->ops = ops;
|
||||
ns->ns_id = 0;
|
||||
RB_CLEAR_NODE(&ns->ns_tree_node);
|
||||
INIT_LIST_HEAD(&ns->ns_list_node);
|
||||
|
||||
if (inum) {
|
||||
ns->inum = inum;
|
||||
return 0;
|
||||
}
|
||||
return proc_alloc_inum(&ns->inum);
|
||||
}
|
||||
|
||||
void __ns_common_free(struct ns_common *ns)
|
||||
{
|
||||
proc_free_inum(ns->inum);
|
||||
}
|
||||
@@ -103,7 +103,7 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
|
||||
if (ns->pid_cachep == NULL)
|
||||
goto out_free_idr;
|
||||
|
||||
err = ns_common_init(&ns->ns, &pidns_operations, true);
|
||||
err = ns_common_init(ns, &pidns_operations);
|
||||
if (err)
|
||||
goto out_free_idr;
|
||||
|
||||
@@ -127,7 +127,7 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
|
||||
return ns;
|
||||
|
||||
out_free_inum:
|
||||
ns_free_inum(&ns->ns);
|
||||
ns_common_free(ns);
|
||||
out_free_idr:
|
||||
idr_destroy(&ns->idr);
|
||||
kmem_cache_free(pid_ns_cachep, ns);
|
||||
@@ -152,7 +152,7 @@ static void destroy_pid_namespace(struct pid_namespace *ns)
|
||||
ns_tree_remove(ns);
|
||||
unregister_pidns_sysctls(ns);
|
||||
|
||||
ns_free_inum(&ns->ns);
|
||||
ns_common_free(ns);
|
||||
|
||||
idr_destroy(&ns->idr);
|
||||
call_rcu(&ns->rcu, delayed_free_pidns);
|
||||
|
||||
@@ -97,7 +97,7 @@ static struct time_namespace *clone_time_ns(struct user_namespace *user_ns,
|
||||
if (!ns->vvar_page)
|
||||
goto fail_free;
|
||||
|
||||
err = ns_common_init(&ns->ns, &timens_operations, true);
|
||||
err = ns_common_init(ns, &timens_operations);
|
||||
if (err)
|
||||
goto fail_free_page;
|
||||
|
||||
@@ -255,7 +255,7 @@ void free_time_ns(struct time_namespace *ns)
|
||||
ns_tree_remove(ns);
|
||||
dec_time_namespaces(ns->ucounts);
|
||||
put_user_ns(ns->user_ns);
|
||||
ns_free_inum(&ns->ns);
|
||||
ns_common_free(ns);
|
||||
__free_page(ns->vvar_page);
|
||||
/* Concurrent nstree traversal depends on a grace period. */
|
||||
kfree_rcu(ns, ns.ns_rcu);
|
||||
|
||||
@@ -126,7 +126,7 @@ int create_user_ns(struct cred *new)
|
||||
|
||||
ns->parent_could_setfcap = cap_raised(new->cap_effective, CAP_SETFCAP);
|
||||
|
||||
ret = ns_common_init(&ns->ns, &userns_operations, true);
|
||||
ret = ns_common_init(ns, &userns_operations);
|
||||
if (ret)
|
||||
goto fail_free;
|
||||
|
||||
@@ -165,7 +165,7 @@ int create_user_ns(struct cred *new)
|
||||
#ifdef CONFIG_PERSISTENT_KEYRINGS
|
||||
key_put(ns->persistent_keyring_register);
|
||||
#endif
|
||||
ns_free_inum(&ns->ns);
|
||||
ns_common_free(ns);
|
||||
fail_free:
|
||||
kmem_cache_free(user_ns_cachep, ns);
|
||||
fail_dec:
|
||||
@@ -220,7 +220,7 @@ static void free_user_ns(struct work_struct *work)
|
||||
#endif
|
||||
retire_userns_sysctls(ns);
|
||||
key_free_user_ns(ns);
|
||||
ns_free_inum(&ns->ns);
|
||||
ns_common_free(ns);
|
||||
/* Concurrent nstree traversal depends on a grace period. */
|
||||
kfree_rcu(ns, ns.ns_rcu);
|
||||
dec_user_namespaces(ucounts);
|
||||
|
||||
@@ -50,7 +50,7 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
|
||||
if (!ns)
|
||||
goto fail_dec;
|
||||
|
||||
err = ns_common_init(&ns->ns, &utsns_operations, true);
|
||||
err = ns_common_init(ns, &utsns_operations);
|
||||
if (err)
|
||||
goto fail_free;
|
||||
|
||||
@@ -98,7 +98,7 @@ void free_uts_ns(struct uts_namespace *ns)
|
||||
ns_tree_remove(ns);
|
||||
dec_uts_namespaces(ns->ucounts);
|
||||
put_user_ns(ns->user_ns);
|
||||
ns_free_inum(&ns->ns);
|
||||
ns_common_free(ns);
|
||||
/* Concurrent nstree traversal depends on a grace period. */
|
||||
kfree_rcu(ns, ns.ns_rcu);
|
||||
}
|
||||
|
||||
@@ -409,7 +409,7 @@ static __net_init int preinit_net(struct net *net, struct user_namespace *user_n
|
||||
ns_ops = NULL;
|
||||
#endif
|
||||
|
||||
ret = ns_common_init(&net->ns, ns_ops, false);
|
||||
ret = ns_common_init(net, ns_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -590,6 +590,7 @@ struct net *copy_net_ns(unsigned long flags,
|
||||
|
||||
if (rv < 0) {
|
||||
put_userns:
|
||||
ns_common_free(net);
|
||||
#ifdef CONFIG_KEYS
|
||||
key_remove_domain(net->key_domain);
|
||||
#endif
|
||||
@@ -712,6 +713,7 @@ static void cleanup_net(struct work_struct *work)
|
||||
/* Finally it is safe to free my network namespace structure */
|
||||
list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
|
||||
list_del_init(&net->exit_list);
|
||||
ns_common_free(net);
|
||||
dec_net_namespaces(net->ucounts);
|
||||
#ifdef CONFIG_KEYS
|
||||
key_remove_domain(net->key_domain);
|
||||
@@ -831,31 +833,12 @@ static void net_ns_net_debugfs(struct net *net)
|
||||
|
||||
static __net_init int net_ns_net_init(struct net *net)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (net == &init_net)
|
||||
net->ns.inum = PROC_NET_INIT_INO;
|
||||
else
|
||||
ret = proc_alloc_inum(&to_ns_common(net)->inum);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
net_ns_net_debugfs(net);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __net_exit void net_ns_net_exit(struct net *net)
|
||||
{
|
||||
/*
|
||||
* Initial network namespace doesn't exit so we don't need any
|
||||
* special checks here.
|
||||
*/
|
||||
ns_free_inum(&net->ns);
|
||||
}
|
||||
|
||||
static struct pernet_operations __net_initdata net_ns_ops = {
|
||||
.init = net_ns_net_init,
|
||||
.exit = net_ns_net_exit,
|
||||
};
|
||||
|
||||
static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = {
|
||||
|
||||
Reference in New Issue
Block a user