Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
ipc
namespace.c
Go to the documentation of this file.
1
/*
2
* linux/ipc/namespace.c
3
* Copyright (C) 2006 Pavel Emelyanov <
[email protected]
> OpenVZ, SWsoft Inc.
4
*/
5
6
#include <linux/ipc.h>
7
#include <linux/msg.h>
8
#include <
linux/ipc_namespace.h
>
9
#include <
linux/rcupdate.h
>
10
#include <
linux/nsproxy.h
>
11
#include <linux/slab.h>
12
#include <linux/fs.h>
13
#include <
linux/mount.h
>
14
#include <
linux/user_namespace.h
>
15
#include <
linux/proc_fs.h
>
16
17
#include "
util.h
"
18
19
static
struct
ipc_namespace
*create_ipc_ns(
struct
task_struct
*tsk,
20
struct
ipc_namespace
*old_ns)
21
{
22
struct
ipc_namespace
*
ns
;
23
int
err
;
24
25
ns =
kmalloc
(
sizeof
(
struct
ipc_namespace
),
GFP_KERNEL
);
26
if
(ns ==
NULL
)
27
return
ERR_PTR(-
ENOMEM
);
28
29
atomic_set
(&ns->
count
, 1);
30
err =
mq_init_ns
(ns);
31
if
(err) {
32
kfree
(ns);
33
return
ERR_PTR(err);
34
}
35
atomic_inc
(&
nr_ipc_ns
);
36
37
sem_init_ns
(ns);
38
msg_init_ns
(ns);
39
shm_init_ns
(ns);
40
41
/*
42
* msgmni has already been computed for the new ipc ns.
43
* Thus, do the ipcns creation notification before registering that
44
* new ipcns in the chain.
45
*/
46
ipcns_notify
(
IPCNS_CREATED
);
47
register_ipcns_notifier
(ns);
48
49
ns->
user_ns
= get_user_ns(
task_cred_xxx
(tsk,
user_ns
));
50
51
return
ns
;
52
}
53
54
struct
ipc_namespace
*
copy_ipcs
(
unsigned
long
flags
,
55
struct
task_struct
*tsk)
56
{
57
struct
ipc_namespace
*ns = tsk->
nsproxy
->ipc_ns;
58
59
if
(!(flags &
CLONE_NEWIPC
))
60
return
get_ipc_ns(ns);
61
return
create_ipc_ns(tsk, ns);
62
}
63
64
/*
65
* free_ipcs - free all ipcs of one type
66
* @ns: the namespace to remove the ipcs from
67
* @ids: the table of ipcs to free
68
* @free: the function called to free each individual ipc
69
*
70
* Called for each kind of ipc when an ipc_namespace exits.
71
*/
72
void
free_ipcs
(
struct
ipc_namespace
*ns,
struct
ipc_ids
*
ids
,
73
void
(*
free
)(
struct
ipc_namespace
*,
struct
kern_ipc_perm
*))
74
{
75
struct
kern_ipc_perm
*
perm
;
76
int
next_id;
77
int
total,
in_use
;
78
79
down_write
(&ids->
rw_mutex
);
80
81
in_use = ids->
in_use
;
82
83
for
(total = 0, next_id = 0; total <
in_use
; next_id++) {
84
perm =
idr_find
(&ids->
ipcs_idr
, next_id);
85
if
(perm ==
NULL
)
86
continue
;
87
ipc_lock_by_ptr(perm);
88
free
(ns, perm);
89
total++;
90
}
91
up_write
(&ids->
rw_mutex
);
92
}
93
94
static
void
free_ipc_ns(
struct
ipc_namespace
*ns)
95
{
96
/*
97
* Unregistering the hotplug notifier at the beginning guarantees
98
* that the ipc namespace won't be freed while we are inside the
99
* callback routine. Since the blocking_notifier_chain_XXX routines
100
* hold a rw lock on the notifier list, unregister_ipcns_notifier()
101
* won't take the rw lock before blocking_notifier_call_chain() has
102
* released the rd lock.
103
*/
104
unregister_ipcns_notifier
(ns);
105
sem_exit_ns(ns);
106
msg_exit_ns(ns);
107
shm_exit_ns(ns);
108
atomic_dec
(&
nr_ipc_ns
);
109
110
/*
111
* Do the ipcns removal notification after decrementing nr_ipc_ns in
112
* order to have a correct value when recomputing msgmni.
113
*/
114
ipcns_notify
(
IPCNS_REMOVED
);
115
put_user_ns(ns->
user_ns
);
116
kfree
(ns);
117
}
118
119
/*
120
* put_ipc_ns - drop a reference to an ipc namespace.
121
* @ns: the namespace to put
122
*
123
* If this is the last task in the namespace exiting, and
124
* it is dropping the refcount to 0, then it can race with
125
* a task in another ipc namespace but in a mounts namespace
126
* which has this ipcns's mqueuefs mounted, doing some action
127
* with one of the mqueuefs files. That can raise the refcount.
128
* So dropping the refcount, and raising the refcount when
129
* accessing it through the VFS, are protected with mq_lock.
130
*
131
* (Clearly, a task raising the refcount on its own ipc_ns
132
* needn't take mq_lock since it can't race with the last task
133
* in the ipcns exiting).
134
*/
135
void
put_ipc_ns
(
struct
ipc_namespace
*ns)
136
{
137
if
(
atomic_dec_and_lock
(&ns->
count
, &
mq_lock
)) {
138
mq_clear_sbinfo
(ns);
139
spin_unlock(&
mq_lock
);
140
mq_put_mnt
(ns);
141
free_ipc_ns(ns);
142
}
143
}
144
145
static
void
*ipcns_get(
struct
task_struct
*
task
)
146
{
147
struct
ipc_namespace
*ns =
NULL
;
148
struct
nsproxy
*
nsproxy
;
149
150
rcu_read_lock();
151
nsproxy = task_nsproxy(task);
152
if
(nsproxy)
153
ns = get_ipc_ns(nsproxy->
ipc_ns
);
154
rcu_read_unlock();
155
156
return
ns
;
157
}
158
159
static
void
ipcns_put(
void
*ns)
160
{
161
return
put_ipc_ns
(ns);
162
}
163
164
static
int
ipcns_install(
struct
nsproxy *nsproxy,
void
*ns)
165
{
166
/* Ditch state from the old ipc namespace */
167
exit_sem
(
current
);
168
put_ipc_ns
(nsproxy->
ipc_ns
);
169
nsproxy->
ipc_ns
= get_ipc_ns(ns);
170
return
0;
171
}
172
173
const
struct
proc_ns_operations
ipcns_operations
= {
174
.name =
"ipc"
,
175
.type =
CLONE_NEWIPC
,
176
.get = ipcns_get,
177
.put = ipcns_put,
178
.install = ipcns_install,
179
};
Generated on Thu Jan 10 2013 14:48:12 for Linux Kernel by
1.8.2