aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorKirill Korotaev <dev@openvz.org>2006-10-02 05:18:20 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-02 10:57:22 -0400
commit73ea41302bab5e02c9e86ab15c509494a550f1db (patch)
tree10971a839dd53a9e18d6c866c9be93517fe8de25 /ipc
parent25b21cb2f6d69b0475b134e0a3e8e269137270fa (diff)
[PATCH] IPC namespace - utils
This patch adds basic IPC namespace functionality to IPC utils: - init_ipc_ns - copy/clone/unshare/free IPC ns - /proc preparations Signed-off-by: Pavel Emelianov <xemul@openvz.org> Signed-off-by: Kirill Korotaev <dev@openvz.org> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Cedric Le Goater <clg@fr.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/util.c132
-rw-r--r--ipc/util.h24
2 files changed, 143 insertions, 13 deletions
diff --git a/ipc/util.c b/ipc/util.c
index 67b6d178db6e..42479e4eec59 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -12,6 +12,9 @@
12 * Mingming Cao <cmm@us.ibm.com> 12 * Mingming Cao <cmm@us.ibm.com>
13 * Mar 2006 - support for audit of ipc object properties 13 * Mar 2006 - support for audit of ipc object properties
14 * Dustin Kirkland <dustin.kirkland@us.ibm.com> 14 * Dustin Kirkland <dustin.kirkland@us.ibm.com>
15 * Jun 2006 - namespaces ssupport
16 * OpenVZ, SWsoft Inc.
17 * Pavel Emelianov <xemul@openvz.org>
15 */ 18 */
16 19
17#include <linux/mm.h> 20#include <linux/mm.h>
@@ -29,6 +32,7 @@
29#include <linux/seq_file.h> 32#include <linux/seq_file.h>
30#include <linux/proc_fs.h> 33#include <linux/proc_fs.h>
31#include <linux/audit.h> 34#include <linux/audit.h>
35#include <linux/nsproxy.h>
32 36
33#include <asm/unistd.h> 37#include <asm/unistd.h>
34 38
@@ -37,10 +41,111 @@
37struct ipc_proc_iface { 41struct ipc_proc_iface {
38 const char *path; 42 const char *path;
39 const char *header; 43 const char *header;
40 struct ipc_ids *ids; 44 int ids;
41 int (*show)(struct seq_file *, void *); 45 int (*show)(struct seq_file *, void *);
42}; 46};
43 47
48struct ipc_namespace init_ipc_ns = {
49 .kref = {
50 .refcount = ATOMIC_INIT(2),
51 },
52};
53
54#ifdef CONFIG_IPC_NS
55static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
56{
57 int err;
58 struct ipc_namespace *ns;
59
60 err = -ENOMEM;
61 ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
62 if (ns == NULL)
63 goto err_mem;
64
65 err = sem_init_ns(ns);
66 if (err)
67 goto err_sem;
68 err = msg_init_ns(ns);
69 if (err)
70 goto err_msg;
71 err = shm_init_ns(ns);
72 if (err)
73 goto err_shm;
74
75 kref_init(&ns->kref);
76 return ns;
77
78err_shm:
79 msg_exit_ns(ns);
80err_msg:
81 sem_exit_ns(ns);
82err_sem:
83 kfree(ns);
84err_mem:
85 return ERR_PTR(err);
86}
87
88int unshare_ipcs(unsigned long unshare_flags, struct ipc_namespace **new_ipc)
89{
90 struct ipc_namespace *new;
91
92 if (unshare_flags & CLONE_NEWIPC) {
93 if (!capable(CAP_SYS_ADMIN))
94 return -EPERM;
95
96 new = clone_ipc_ns(current->nsproxy->ipc_ns);
97 if (IS_ERR(new))
98 return PTR_ERR(new);
99
100 *new_ipc = new;
101 }
102
103 return 0;
104}
105
106int copy_ipcs(unsigned long flags, struct task_struct *tsk)
107{
108 struct ipc_namespace *old_ns = tsk->nsproxy->ipc_ns;
109 struct ipc_namespace *new_ns;
110 int err = 0;
111
112 if (!old_ns)
113 return 0;
114
115 get_ipc_ns(old_ns);
116
117 if (!(flags & CLONE_NEWIPC))
118 return 0;
119
120 if (!capable(CAP_SYS_ADMIN)) {
121 err = -EPERM;
122 goto out;
123 }
124
125 new_ns = clone_ipc_ns(old_ns);
126 if (!new_ns) {
127 err = -ENOMEM;
128 goto out;
129 }
130
131 tsk->nsproxy->ipc_ns = new_ns;
132out:
133 put_ipc_ns(old_ns);
134 return err;
135}
136
137void free_ipc_ns(struct kref *kref)
138{
139 struct ipc_namespace *ns;
140
141 ns = container_of(kref, struct ipc_namespace, kref);
142 sem_exit_ns(ns);
143 msg_exit_ns(ns);
144 shm_exit_ns(ns);
145 kfree(ns);
146}
147#endif
148
44/** 149/**
45 * ipc_init - initialise IPC subsystem 150 * ipc_init - initialise IPC subsystem
46 * 151 *
@@ -67,7 +172,7 @@ __initcall(ipc_init);
67 * array itself. 172 * array itself.
68 */ 173 */
69 174
70void __init ipc_init_ids(struct ipc_ids* ids, int size) 175void __ipc_init ipc_init_ids(struct ipc_ids* ids, int size)
71{ 176{
72 int i; 177 int i;
73 178
@@ -110,8 +215,7 @@ static struct file_operations sysvipc_proc_fops;
110 * @show: show routine. 215 * @show: show routine.
111 */ 216 */
112void __init ipc_init_proc_interface(const char *path, const char *header, 217void __init ipc_init_proc_interface(const char *path, const char *header,
113 struct ipc_ids *ids, 218 int ids, int (*show)(struct seq_file *, void *))
114 int (*show)(struct seq_file *, void *))
115{ 219{
116 struct proc_dir_entry *pde; 220 struct proc_dir_entry *pde;
117 struct ipc_proc_iface *iface; 221 struct ipc_proc_iface *iface;
@@ -635,6 +739,9 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
635 struct ipc_proc_iface *iface = s->private; 739 struct ipc_proc_iface *iface = s->private;
636 struct kern_ipc_perm *ipc = it; 740 struct kern_ipc_perm *ipc = it;
637 loff_t p; 741 loff_t p;
742 struct ipc_ids *ids;
743
744 ids = current->nsproxy->ipc_ns->ids[iface->ids];
638 745
639 /* If we had an ipc id locked before, unlock it */ 746 /* If we had an ipc id locked before, unlock it */
640 if (ipc && ipc != SEQ_START_TOKEN) 747 if (ipc && ipc != SEQ_START_TOKEN)
@@ -644,8 +751,8 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
644 * p = *pos - 1 (because id 0 starts at position 1) 751 * p = *pos - 1 (because id 0 starts at position 1)
645 * + 1 (because we increment the position by one) 752 * + 1 (because we increment the position by one)
646 */ 753 */
647 for (p = *pos; p <= iface->ids->max_id; p++) { 754 for (p = *pos; p <= ids->max_id; p++) {
648 if ((ipc = ipc_lock(iface->ids, p)) != NULL) { 755 if ((ipc = ipc_lock(ids, p)) != NULL) {
649 *pos = p + 1; 756 *pos = p + 1;
650 return ipc; 757 return ipc;
651 } 758 }
@@ -664,12 +771,15 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
664 struct ipc_proc_iface *iface = s->private; 771 struct ipc_proc_iface *iface = s->private;
665 struct kern_ipc_perm *ipc; 772 struct kern_ipc_perm *ipc;
666 loff_t p; 773 loff_t p;
774 struct ipc_ids *ids;
775
776 ids = current->nsproxy->ipc_ns->ids[iface->ids];
667 777
668 /* 778 /*
669 * Take the lock - this will be released by the corresponding 779 * Take the lock - this will be released by the corresponding
670 * call to stop(). 780 * call to stop().
671 */ 781 */
672 mutex_lock(&iface->ids->mutex); 782 mutex_lock(&ids->mutex);
673 783
674 /* pos < 0 is invalid */ 784 /* pos < 0 is invalid */
675 if (*pos < 0) 785 if (*pos < 0)
@@ -680,8 +790,8 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
680 return SEQ_START_TOKEN; 790 return SEQ_START_TOKEN;
681 791
682 /* Find the (pos-1)th ipc */ 792 /* Find the (pos-1)th ipc */
683 for (p = *pos - 1; p <= iface->ids->max_id; p++) { 793 for (p = *pos - 1; p <= ids->max_id; p++) {
684 if ((ipc = ipc_lock(iface->ids, p)) != NULL) { 794 if ((ipc = ipc_lock(ids, p)) != NULL) {
685 *pos = p + 1; 795 *pos = p + 1;
686 return ipc; 796 return ipc;
687 } 797 }
@@ -693,13 +803,15 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it)
693{ 803{
694 struct kern_ipc_perm *ipc = it; 804 struct kern_ipc_perm *ipc = it;
695 struct ipc_proc_iface *iface = s->private; 805 struct ipc_proc_iface *iface = s->private;
806 struct ipc_ids *ids;
696 807
697 /* If we had a locked segment, release it */ 808 /* If we had a locked segment, release it */
698 if (ipc && ipc != SEQ_START_TOKEN) 809 if (ipc && ipc != SEQ_START_TOKEN)
699 ipc_unlock(ipc); 810 ipc_unlock(ipc);
700 811
812 ids = current->nsproxy->ipc_ns->ids[iface->ids];
701 /* Release the lock we took in start() */ 813 /* Release the lock we took in start() */
702 mutex_unlock(&iface->ids->mutex); 814 mutex_unlock(&ids->mutex);
703} 815}
704 816
705static int sysvipc_proc_show(struct seq_file *s, void *it) 817static int sysvipc_proc_show(struct seq_file *s, void *it)
diff --git a/ipc/util.h b/ipc/util.h
index 0181553d31d8..c8fd6b9d77b5 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -3,6 +3,8 @@
3 * Copyright (C) 1999 Christoph Rohland 3 * Copyright (C) 1999 Christoph Rohland
4 * 4 *
5 * ipc helper functions (c) 1999 Manfred Spraul <manfred@colorfullife.com> 5 * ipc helper functions (c) 1999 Manfred Spraul <manfred@colorfullife.com>
6 * namespaces support. 2006 OpenVZ, SWsoft Inc.
7 * Pavel Emelianov <xemul@openvz.org>
6 */ 8 */
7 9
8#ifndef _IPC_UTIL_H 10#ifndef _IPC_UTIL_H
@@ -15,6 +17,14 @@ void sem_init (void);
15void msg_init (void); 17void msg_init (void);
16void shm_init (void); 18void shm_init (void);
17 19
20int sem_init_ns(struct ipc_namespace *ns);
21int msg_init_ns(struct ipc_namespace *ns);
22int shm_init_ns(struct ipc_namespace *ns);
23
24void sem_exit_ns(struct ipc_namespace *ns);
25void msg_exit_ns(struct ipc_namespace *ns);
26void shm_exit_ns(struct ipc_namespace *ns);
27
18struct ipc_id_ary { 28struct ipc_id_ary {
19 int size; 29 int size;
20 struct kern_ipc_perm *p[0]; 30 struct kern_ipc_perm *p[0];
@@ -31,15 +41,23 @@ struct ipc_ids {
31}; 41};
32 42
33struct seq_file; 43struct seq_file;
34void __init ipc_init_ids(struct ipc_ids* ids, int size); 44#ifdef CONFIG_IPC_NS
45#define __ipc_init
46#else
47#define __ipc_init __init
48#endif
49void __ipc_init ipc_init_ids(struct ipc_ids *ids, int size);
35#ifdef CONFIG_PROC_FS 50#ifdef CONFIG_PROC_FS
36void __init ipc_init_proc_interface(const char *path, const char *header, 51void __init ipc_init_proc_interface(const char *path, const char *header,
37 struct ipc_ids *ids, 52 int ids, int (*show)(struct seq_file *, void *));
38 int (*show)(struct seq_file *, void *));
39#else 53#else
40#define ipc_init_proc_interface(path, header, ids, show) do {} while (0) 54#define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
41#endif 55#endif
42 56
57#define IPC_SEM_IDS 0
58#define IPC_MSG_IDS 1
59#define IPC_SHM_IDS 2
60
43/* must be called with ids->mutex acquired.*/ 61/* must be called with ids->mutex acquired.*/
44int ipc_findkey(struct ipc_ids* ids, key_t key); 62int ipc_findkey(struct ipc_ids* ids, key_t key);
45int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size); 63int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size);