aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill Korotaev <dev@openvz.org>2006-10-02 05:18:19 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-02 10:57:22 -0400
commit25b21cb2f6d69b0475b134e0a3e8e269137270fa (patch)
treecd9c3966408c0ca5903249437c35ff35961de544
parentc0b2fc316599d6cd875b6b8cafa67f03b9512b4d (diff)
[PATCH] IPC namespace core
This patch set allows to unshare IPCs and have a private set of IPC objects (sem, shm, msg) inside namespace. Basically, it is another building block of containers functionality. This patch implements core IPC namespace changes: - ipc_namespace structure - new config option CONFIG_IPC_NS - adds CLONE_NEWIPC flag - unshare support [clg@fr.ibm.com: small fix for unshare of ipc namespace] [akpm@osdl.org: build fix] Signed-off-by: Pavel Emelianov <xemul@openvz.org> Signed-off-by: Kirill Korotaev <dev@openvz.org> Signed-off-by: Cedric Le Goater <clg@fr.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/init_task.h1
-rw-r--r--include/linux/ipc.h36
-rw-r--r--include/linux/nsproxy.h2
-rw-r--r--include/linux/sched.h1
-rw-r--r--init/Kconfig9
-rw-r--r--kernel/fork.c22
-rw-r--r--kernel/nsproxy.c41
7 files changed, 95 insertions, 17 deletions
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index e08531ec32f0..ceecf69dfa39 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -74,6 +74,7 @@ extern struct nsproxy init_nsproxy;
74 .count = ATOMIC_INIT(1), \ 74 .count = ATOMIC_INIT(1), \
75 .nslock = SPIN_LOCK_UNLOCKED, \ 75 .nslock = SPIN_LOCK_UNLOCKED, \
76 .uts_ns = &init_uts_ns, \ 76 .uts_ns = &init_uts_ns, \
77 .ipc_ns = &init_ipc_ns, \
77 .namespace = NULL, \ 78 .namespace = NULL, \
78} 79}
79 80
diff --git a/include/linux/ipc.h b/include/linux/ipc.h
index b291189737e7..36027b10f283 100644
--- a/include/linux/ipc.h
+++ b/include/linux/ipc.h
@@ -2,6 +2,7 @@
2#define _LINUX_IPC_H 2#define _LINUX_IPC_H
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <linux/kref.h>
5 6
6#define IPC_PRIVATE ((__kernel_key_t) 0) 7#define IPC_PRIVATE ((__kernel_key_t) 0)
7 8
@@ -68,6 +69,41 @@ struct kern_ipc_perm
68 void *security; 69 void *security;
69}; 70};
70 71
72struct ipc_ids;
73struct ipc_namespace {
74 struct kref kref;
75 struct ipc_ids *ids[3];
76
77 int sem_ctls[4];
78 int used_sems;
79
80 int msg_ctlmax;
81 int msg_ctlmnb;
82 int msg_ctlmni;
83
84 size_t shm_ctlmax;
85 size_t shm_ctlall;
86 int shm_ctlmni;
87 int shm_tot;
88};
89
90extern struct ipc_namespace init_ipc_ns;
91extern void free_ipc_ns(struct kref *kref);
92extern int copy_ipcs(unsigned long flags, struct task_struct *tsk);
93extern int unshare_ipcs(unsigned long flags, struct ipc_namespace **ns);
94
95static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
96{
97 if (ns)
98 kref_get(&ns->kref);
99 return ns;
100}
101
102static inline void put_ipc_ns(struct ipc_namespace *ns)
103{
104 kref_put(&ns->kref, free_ipc_ns);
105}
106
71#endif /* __KERNEL__ */ 107#endif /* __KERNEL__ */
72 108
73#endif /* _LINUX_IPC_H */ 109#endif /* _LINUX_IPC_H */
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 9c2e0ad508db..f6baecdeecd6 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -6,6 +6,7 @@
6 6
7struct namespace; 7struct namespace;
8struct uts_namespace; 8struct uts_namespace;
9struct ipc_namespace;
9 10
10/* 11/*
11 * A structure to contain pointers to all per-process 12 * A structure to contain pointers to all per-process
@@ -23,6 +24,7 @@ struct nsproxy {
23 atomic_t count; 24 atomic_t count;
24 spinlock_t nslock; 25 spinlock_t nslock;
25 struct uts_namespace *uts_ns; 26 struct uts_namespace *uts_ns;
27 struct ipc_namespace *ipc_ns;
26 struct namespace *namespace; 28 struct namespace *namespace;
27}; 29};
28extern struct nsproxy init_nsproxy; 30extern struct nsproxy init_nsproxy;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index a973e7012315..9ba959e34266 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -25,6 +25,7 @@
25#define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */ 25#define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */
26#define CLONE_STOPPED 0x02000000 /* Start in stopped state */ 26#define CLONE_STOPPED 0x02000000 /* Start in stopped state */
27#define CLONE_NEWUTS 0x04000000 /* New utsname group? */ 27#define CLONE_NEWUTS 0x04000000 /* New utsname group? */
28#define CLONE_NEWIPC 0x08000000 /* New ipcs */
28 29
29/* 30/*
30 * Scheduling policies 31 * Scheduling policies
diff --git a/init/Kconfig b/init/Kconfig
index b0ea97554473..10382931eead 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -115,6 +115,15 @@ config SYSVIPC
115 section 6.4 of the Linux Programmer's Guide, available from 115 section 6.4 of the Linux Programmer's Guide, available from
116 <http://www.tldp.org/guides.html>. 116 <http://www.tldp.org/guides.html>.
117 117
118config IPC_NS
119 bool "IPC Namespaces"
120 depends on SYSVIPC
121 default n
122 help
123 Support ipc namespaces. This allows containers, i.e. virtual
124 environments, to use ipc namespaces to provide different ipc
125 objects for different servers. If unsure, say N.
126
118config POSIX_MQUEUE 127config POSIX_MQUEUE
119 bool "POSIX Message Queues" 128 bool "POSIX Message Queues"
120 depends on NET && EXPERIMENTAL 129 depends on NET && EXPERIMENTAL
diff --git a/kernel/fork.c b/kernel/fork.c
index 208dd99f13bc..d6cc56558507 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1608,13 +1608,15 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
1608 struct sem_undo_list *new_ulist = NULL; 1608 struct sem_undo_list *new_ulist = NULL;
1609 struct nsproxy *new_nsproxy = NULL, *old_nsproxy = NULL; 1609 struct nsproxy *new_nsproxy = NULL, *old_nsproxy = NULL;
1610 struct uts_namespace *uts, *new_uts = NULL; 1610 struct uts_namespace *uts, *new_uts = NULL;
1611 struct ipc_namespace *ipc, *new_ipc = NULL;
1611 1612
1612 check_unshare_flags(&unshare_flags); 1613 check_unshare_flags(&unshare_flags);
1613 1614
1614 /* Return -EINVAL for all unsupported flags */ 1615 /* Return -EINVAL for all unsupported flags */
1615 err = -EINVAL; 1616 err = -EINVAL;
1616 if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| 1617 if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
1617 CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|CLONE_NEWUTS)) 1618 CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
1619 CLONE_NEWUTS|CLONE_NEWIPC))
1618 goto bad_unshare_out; 1620 goto bad_unshare_out;
1619 1621
1620 if ((err = unshare_thread(unshare_flags))) 1622 if ((err = unshare_thread(unshare_flags)))
@@ -1633,18 +1635,20 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
1633 goto bad_unshare_cleanup_fd; 1635 goto bad_unshare_cleanup_fd;
1634 if ((err = unshare_utsname(unshare_flags, &new_uts))) 1636 if ((err = unshare_utsname(unshare_flags, &new_uts)))
1635 goto bad_unshare_cleanup_semundo; 1637 goto bad_unshare_cleanup_semundo;
1638 if ((err = unshare_ipcs(unshare_flags, &new_ipc)))
1639 goto bad_unshare_cleanup_uts;
1636 1640
1637 if (new_ns || new_uts) { 1641 if (new_ns || new_uts || new_ipc) {
1638 old_nsproxy = current->nsproxy; 1642 old_nsproxy = current->nsproxy;
1639 new_nsproxy = dup_namespaces(old_nsproxy); 1643 new_nsproxy = dup_namespaces(old_nsproxy);
1640 if (!new_nsproxy) { 1644 if (!new_nsproxy) {
1641 err = -ENOMEM; 1645 err = -ENOMEM;
1642 goto bad_unshare_cleanup_uts; 1646 goto bad_unshare_cleanup_ipc;
1643 } 1647 }
1644 } 1648 }
1645 1649
1646 if (new_fs || new_ns || new_sigh || new_mm || new_fd || new_ulist || 1650 if (new_fs || new_ns || new_sigh || new_mm || new_fd || new_ulist ||
1647 new_uts) { 1651 new_uts || new_ipc) {
1648 1652
1649 task_lock(current); 1653 task_lock(current);
1650 1654
@@ -1692,12 +1696,22 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
1692 new_uts = uts; 1696 new_uts = uts;
1693 } 1697 }
1694 1698
1699 if (new_ipc) {
1700 ipc = current->nsproxy->ipc_ns;
1701 current->nsproxy->ipc_ns = new_ipc;
1702 new_ipc = ipc;
1703 }
1704
1695 task_unlock(current); 1705 task_unlock(current);
1696 } 1706 }
1697 1707
1698 if (new_nsproxy) 1708 if (new_nsproxy)
1699 put_nsproxy(new_nsproxy); 1709 put_nsproxy(new_nsproxy);
1700 1710
1711bad_unshare_cleanup_ipc:
1712 if (new_ipc)
1713 put_ipc_ns(new_ipc);
1714
1701bad_unshare_cleanup_uts: 1715bad_unshare_cleanup_uts:
1702 if (new_uts) 1716 if (new_uts)
1703 put_uts_ns(new_uts); 1717 put_uts_ns(new_uts);
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 8246813335cc..8d6c852dc51e 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -7,6 +7,10 @@
7 * modify it under the terms of the GNU General Public License as 7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2 of the 8 * published by the Free Software Foundation, version 2 of the
9 * License. 9 * License.
10 *
11 * Jun 2006 - namespaces support
12 * OpenVZ, SWsoft Inc.
13 * Pavel Emelianov <xemul@openvz.org>
10 */ 14 */
11 15
12#include <linux/module.h> 16#include <linux/module.h>
@@ -62,6 +66,8 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig)
62 get_namespace(ns->namespace); 66 get_namespace(ns->namespace);
63 if (ns->uts_ns) 67 if (ns->uts_ns)
64 get_uts_ns(ns->uts_ns); 68 get_uts_ns(ns->uts_ns);
69 if (ns->ipc_ns)
70 get_ipc_ns(ns->ipc_ns);
65 } 71 }
66 72
67 return ns; 73 return ns;
@@ -82,7 +88,7 @@ int copy_namespaces(int flags, struct task_struct *tsk)
82 88
83 get_nsproxy(old_ns); 89 get_nsproxy(old_ns);
84 90
85 if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS))) 91 if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
86 return 0; 92 return 0;
87 93
88 new_ns = clone_namespaces(old_ns); 94 new_ns = clone_namespaces(old_ns);
@@ -94,24 +100,31 @@ int copy_namespaces(int flags, struct task_struct *tsk)
94 tsk->nsproxy = new_ns; 100 tsk->nsproxy = new_ns;
95 101
96 err = copy_namespace(flags, tsk); 102 err = copy_namespace(flags, tsk);
97 if (err) { 103 if (err)
98 tsk->nsproxy = old_ns; 104 goto out_ns;
99 put_nsproxy(new_ns);
100 goto out;
101 }
102 105
103 err = copy_utsname(flags, tsk); 106 err = copy_utsname(flags, tsk);
104 if (err) { 107 if (err)
105 if (new_ns->namespace) 108 goto out_uts;
106 put_namespace(new_ns->namespace); 109
107 tsk->nsproxy = old_ns; 110 err = copy_ipcs(flags, tsk);
108 put_nsproxy(new_ns); 111 if (err)
109 goto out; 112 goto out_ipc;
110 }
111 113
112out: 114out:
113 put_nsproxy(old_ns); 115 put_nsproxy(old_ns);
114 return err; 116 return err;
117
118out_ipc:
119 if (new_ns->uts_ns)
120 put_uts_ns(new_ns->uts_ns);
121out_uts:
122 if (new_ns->namespace)
123 put_namespace(new_ns->namespace);
124out_ns:
125 tsk->nsproxy = old_ns;
126 put_nsproxy(new_ns);
127 goto out;
115} 128}
116 129
117void free_nsproxy(struct nsproxy *ns) 130void free_nsproxy(struct nsproxy *ns)
@@ -120,5 +133,7 @@ void free_nsproxy(struct nsproxy *ns)
120 put_namespace(ns->namespace); 133 put_namespace(ns->namespace);
121 if (ns->uts_ns) 134 if (ns->uts_ns)
122 put_uts_ns(ns->uts_ns); 135 put_uts_ns(ns->uts_ns);
136 if (ns->ipc_ns)
137 put_ipc_ns(ns->ipc_ns);
123 kfree(ns); 138 kfree(ns);
124} 139}