From: "Serge E. Hallyn" This patch defines the uts namespace and some manipulators. Adds the uts namespace to task_struct, and initializes a system-wide init namespace. It leaves a #define for system_utsname so sysctl will compile. This define will be removed in a separate patch. Signed-off-by: Serge Hallyn Cc: Kirill Korotaev Cc: "Eric W. Biederman" Cc: Herbert Poetzl Cc: Andrey Savochkin Signed-off-by: Andrew Morton --- include/linux/init_task.h | 2 + include/linux/nsproxy.h | 2 + include/linux/sched.h | 1 include/linux/utsname.h | 52 +++++++++++++++++++++++++++++++++--- init/Kconfig | 8 +++++ init/version.c | 22 +++++++++------ kernel/Makefile | 1 kernel/nsproxy.c | 14 +++++++++ kernel/utsname.c | 43 +++++++++++++++++++++++++++++ 9 files changed, 133 insertions(+), 12 deletions(-) diff -puN include/linux/init_task.h~namespaces-utsname-implement-utsname-namespaces include/linux/init_task.h --- a/include/linux/init_task.h~namespaces-utsname-implement-utsname-namespaces +++ a/include/linux/init_task.h @@ -3,6 +3,7 @@ #include #include +#include #define INIT_FDTABLE \ { \ @@ -70,6 +71,7 @@ extern struct nsproxy init_nsproxy; #define INIT_NSPROXY(nsproxy) { \ .count = ATOMIC_INIT(1), \ .nslock = SPIN_LOCK_UNLOCKED, \ + .uts_ns = &init_uts_ns, \ .namespace = NULL, \ } diff -puN include/linux/nsproxy.h~namespaces-utsname-implement-utsname-namespaces include/linux/nsproxy.h --- a/include/linux/nsproxy.h~namespaces-utsname-implement-utsname-namespaces +++ a/include/linux/nsproxy.h @@ -5,6 +5,7 @@ #include struct namespace; +struct uts_namespace; /* * A structure to contain pointers to all per-process @@ -21,6 +22,7 @@ struct namespace; struct nsproxy { atomic_t count; spinlock_t nslock; + struct uts_namespace *uts_ns; struct namespace *namespace; }; extern struct nsproxy init_nsproxy; diff -puN include/linux/sched.h~namespaces-utsname-implement-utsname-namespaces include/linux/sched.h --- a/include/linux/sched.h~namespaces-utsname-implement-utsname-namespaces +++ a/include/linux/sched.h @@ -771,6 +771,7 @@ static inline void prefetch_stack(struct struct audit_context; /* See audit.c */ struct mempolicy; struct pipe_inode_info; +struct uts_namespace; enum sleep_type { SLEEP_NORMAL, diff -puN include/linux/utsname.h~namespaces-utsname-implement-utsname-namespaces include/linux/utsname.h --- a/include/linux/utsname.h~namespaces-utsname-implement-utsname-namespaces +++ a/include/linux/utsname.h @@ -1,6 +1,11 @@ #ifndef _LINUX_UTSNAME_H #define _LINUX_UTSNAME_H +#include +#include +#include +#include + #define __OLD_UTS_LEN 8 struct oldold_utsname { @@ -30,17 +35,58 @@ struct new_utsname { char domainname[65]; }; -extern struct new_utsname system_utsname; +struct uts_namespace { + struct kref kref; + struct new_utsname name; +}; +extern struct uts_namespace init_uts_ns; + +static inline void get_uts_ns(struct uts_namespace *ns) +{ + kref_get(&ns->kref); +} + +#ifdef CONFIG_UTS_NS +extern int copy_utsname(int flags, struct task_struct *tsk); +extern void free_uts_ns(struct kref *kref); + +static inline void put_uts_ns(struct uts_namespace *ns) +{ + kref_put(&ns->kref, free_uts_ns); +} + +static inline void exit_utsname(struct task_struct *p) +{ + struct uts_namespace *uts_ns = p->nsproxy->uts_ns; + if (uts_ns) { + put_uts_ns(uts_ns); + } +} + +#else +static inline int copy_utsname(int flags, struct task_struct *tsk) +{ + return 0; +} +static inline void put_uts_ns(struct uts_namespace *ns) +{ +} +static inline void exit_utsname(struct task_struct *p) +{ +} +#endif static inline struct new_utsname *utsname(void) { - return &system_utsname; + return ¤t->nsproxy->uts_ns->name; } static inline struct new_utsname *init_utsname(void) { - return &system_utsname; + return &init_uts_ns.name; } +#define system_utsname init_uts_ns.name + extern struct rw_semaphore uts_sem; #endif diff -puN init/Kconfig~namespaces-utsname-implement-utsname-namespaces init/Kconfig --- a/init/Kconfig~namespaces-utsname-implement-utsname-namespaces +++ a/init/Kconfig @@ -220,6 +220,14 @@ config SYSCTL building a kernel for install/rescue disks or your system is very limited in memory. +config UTS_NS + bool "UTS Namespaces" + default n + help + Support uts namespaces. This allows containers, i.e. + vservers, to use uts namespaces to provide different + uts info for different servers. If unsure, say N. + config AUDIT bool "Auditing support" depends on NET diff -puN init/version.c~namespaces-utsname-implement-utsname-namespaces init/version.c --- a/init/version.c~namespaces-utsname-implement-utsname-namespaces +++ a/init/version.c @@ -11,23 +11,27 @@ #include #include #include +#include #define version(a) Version_ ## a #define version_string(a) version(a) int version_string(LINUX_VERSION_CODE); -struct new_utsname system_utsname = { - .sysname = UTS_SYSNAME, - .nodename = UTS_NODENAME, - .release = UTS_RELEASE, - .version = UTS_VERSION, - .machine = UTS_MACHINE, - .domainname = UTS_DOMAINNAME, +struct uts_namespace init_uts_ns = { + .kref = { + .refcount = ATOMIC_INIT(2), + }, + .name = { + .sysname = UTS_SYSNAME, + .nodename = UTS_NODENAME, + .release = UTS_RELEASE, + .version = UTS_VERSION, + .machine = UTS_MACHINE, + .domainname = UTS_DOMAINNAME, + }, }; -EXPORT_SYMBOL(system_utsname); - const char linux_banner[] = "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; diff -puN kernel/Makefile~namespaces-utsname-implement-utsname-namespaces kernel/Makefile --- a/kernel/Makefile~namespaces-utsname-implement-utsname-namespaces +++ a/kernel/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ obj-$(CONFIG_SECCOMP) += seccomp.o obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o obj-$(CONFIG_RELAY) += relay.o +obj-$(CONFIG_UTS_NS) += utsname.o obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o obj-$(CONFIG_TASKSTATS) += taskstats.o diff -puN kernel/nsproxy.c~namespaces-utsname-implement-utsname-namespaces kernel/nsproxy.c --- a/kernel/nsproxy.c~namespaces-utsname-implement-utsname-namespaces +++ a/kernel/nsproxy.c @@ -13,6 +13,7 @@ #include #include #include +#include static inline void get_nsproxy(struct nsproxy *ns) { @@ -56,6 +57,8 @@ struct nsproxy *dup_namespaces(struct ns if (ns) { if (ns->namespace) get_namespace(ns->namespace); + if (ns->uts_ns) + get_uts_ns(ns->uts_ns); } return ns; @@ -94,6 +97,15 @@ int copy_namespaces(int flags, struct ta goto out; } + err = copy_utsname(flags, tsk); + if (err) { + if (new_ns->namespace) + put_namespace(new_ns->namespace); + tsk->nsproxy = old_ns; + put_nsproxy(new_ns); + goto out; + } + out: put_nsproxy(old_ns); return err; @@ -103,5 +115,7 @@ void free_nsproxy(struct nsproxy *ns) { if (ns->namespace) put_namespace(ns->namespace); + if (ns->uts_ns) + put_uts_ns(ns->uts_ns); kfree(ns); } diff -puN /dev/null kernel/utsname.c --- /dev/null +++ a/kernel/utsname.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2004 IBM Corporation + * + * Author: Serge Hallyn + * + * 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, version 2 of the + * License. + */ + +#include +#include +#include +#include +#include + +/* + * Copy task tsk's utsname namespace, or clone it if flags + * specifies CLONE_NEWUTS. In latter case, changes to the + * utsname of this process won't be seen by parent, and vice + * versa. + */ +int copy_utsname(int flags, struct task_struct *tsk) +{ + struct uts_namespace *old_ns = tsk->nsproxy->uts_ns; + int err = 0; + + if (!old_ns) + return 0; + + get_uts_ns(old_ns); + + return err; +} + +void free_uts_ns(struct kref *kref) +{ + struct uts_namespace *ns; + + ns = container_of(kref, struct uts_namespace, kref); + kfree(ns); +} _