{
struct vfsmount *mnt;
struct mount *m;
- struct mnt_namespace *ns;
struct path root;
- mnt = vfs_kern_mount(&rootfs_fs_type, 0, "rootfs", NULL);
+ mnt = vfs_kern_mount(&rootfs_fs_type, 0, "rootfs", initramfs_options);
if (IS_ERR(mnt))
panic("Can't create rootfs");
return 0;
}
- if (ns->ops->type != CLONE_NEWPID)
+#ifdef CONFIG_PID_NS
+static int proc_parse_pidns_param(struct fs_context *fc,
+ struct fs_parameter *param,
+ struct fs_parse_result *result)
+{
+ struct proc_fs_context *ctx = fc->fs_private;
+ struct pid_namespace *target, *active = task_active_pid_ns(current);
+ struct ns_common *ns;
+ struct file *ns_filp __free(fput) = NULL;
+
+ switch (param->type) {
+ case fs_value_is_file:
+ /* came through fsconfig, steal the file reference */
+ ns_filp = no_free_ptr(param->file);
+ break;
+ case fs_value_is_string:
+ ns_filp = filp_open(param->string, O_RDONLY, 0);
+ break;
+ default:
+ WARN_ON_ONCE(true);
+ break;
+ }
+ if (!ns_filp)
+ ns_filp = ERR_PTR(-EBADF);
+ if (IS_ERR(ns_filp)) {
+ errorfc(fc, "could not get file from pidns argument");
+ return PTR_ERR(ns_filp);
+ }
+
+ if (!proc_ns_file(ns_filp))
+ return invalfc(fc, "pidns argument is not an nsfs file");
+ ns = get_proc_ns(file_inode(ns_filp));
++ if (ns->ns_type != CLONE_NEWPID)
+ return invalfc(fc, "pidns argument is not a pidns file");
+ target = container_of(ns, struct pid_namespace, ns);
+
+ /*
+ * pidns= is shorthand for joining the pidns to get a fsopen fd, so the
+ * permission model should be the same as pidns_install().
+ */
+ if (!ns_capable(target->user_ns, CAP_SYS_ADMIN)) {
+ errorfc(fc, "insufficient permissions to set pidns");
+ return -EPERM;
+ }
+ if (!pidns_is_ancestor(target, active))
+ return invalfc(fc, "cannot set pidns to non-descendant pidns");
+
+ put_pid_ns(ctx->pid_ns);
+ ctx->pid_ns = get_pid_ns(target);
+ put_user_ns(fc->user_ns);
+ fc->user_ns = get_user_ns(ctx->pid_ns->user_ns);
+ return 0;
+}
+#endif /* CONFIG_PID_NS */
+
static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
struct proc_fs_context *ctx = fc->fs_private;
#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
-
- void free_cgroup_ns(struct cgroup_namespace *ns);
-
- struct cgroup_namespace *copy_cgroup_ns(u64 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(u64 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
void cgroup_enter_frozen(void);
--- /dev/null
-struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
+ /* SPDX-License-Identifier: GPL-2.0 */
+ #ifndef _LINUX_CGROUP_NAMESPACE_H
+ #define _LINUX_CGROUP_NAMESPACE_H
+
+ #include <linux/ns_common.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);
+
-copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns,
++struct cgroup_namespace *copy_cgroup_ns(u64 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)
+ {
+ ns_ref_inc(ns);
+ }
+
+ static inline void put_cgroup_ns(struct cgroup_namespace *ns)
+ {
+ if (ns_ref_put(ns))
+ 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(u64 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 */
#endif
#if defined(CONFIG_IPC_NS)
-extern struct ipc_namespace *copy_ipcs(unsigned long flags,
+ static inline struct ipc_namespace *to_ipc_ns(struct ns_common *ns)
+ {
+ return container_of(ns, struct ipc_namespace, ns);
+ }
+
+extern struct ipc_namespace *copy_ipcs(u64 flags,
struct user_namespace *user_ns, struct ipc_namespace *ns);
static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
struct user_namespace;
struct ns_common;
-extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
+ extern struct mnt_namespace init_mnt_ns;
+
+extern struct mnt_namespace *copy_mnt_ns(u64, struct mnt_namespace *,
struct user_namespace *, struct fs_struct *);
extern void put_mnt_ns(struct mnt_namespace *ns);
DEFINE_FREE(put_mnt_ns, struct mnt_namespace *, if (!IS_ERR_OR_NULL(_T)) put_mnt_ns(_T))
--- /dev/null
-extern struct uts_namespace *copy_utsname(unsigned long flags,
+ /* 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)
+ {
+ ns_ref_inc(ns);
+ }
+
-static inline struct uts_namespace *copy_utsname(unsigned long flags,
++extern struct uts_namespace *copy_utsname(u64 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 (ns_ref_put(ns))
+ 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(u64 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 */
parent = ns->parent;
destroy_pid_namespace(ns);
ns = parent;
- } while (ns != &init_pid_ns && refcount_dec_and_test(&ns->ns.count));
+ } while (ns != &init_pid_ns && ns_ref_put(ns));
}
-struct pid_namespace *copy_pid_ns(unsigned long flags,
+struct pid_namespace *copy_pid_ns(u64 flags,
struct user_namespace *user_ns, struct pid_namespace *old_ns)
{
if (!(flags & CLONE_NEWPID))