Blame view

ipc/msg.c 23.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   * linux/ipc/msg.c
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
3
   * Copyright (C) 1992 Krishna Balasubramanian
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
8
9
10
11
12
13
14
   *
   * Removed all the remaining kerneld mess
   * Catch the -EFAULT stuff properly
   * Use GFP_KERNEL for messages as in 1.2
   * Fixed up the unchecked user space derefs
   * Copyright (C) 1998 Alan Cox & Andi Kleen
   *
   * /proc/sysvipc/msg support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
   *
   * mostly rewritten, threaded and wake-one semantics added
   * MSGMAX limit removed, sysctl's added
624dffcbc   Christian Kujau   correct email add...
15
   * (c) 1999 Manfred Spraul <manfred@colorfullife.com>
073115d6b   Steve Grubb   [PATCH] Rework of...
16
17
18
   *
   * support for audit of ipc object properties and permission changes
   * Dustin Kirkland <dustin.kirkland@us.ibm.com>
1e7869373   Kirill Korotaev   [PATCH] IPC names...
19
20
21
22
   *
   * namespaces support
   * OpenVZ, SWsoft Inc.
   * Pavel Emelianov <xemul@openvz.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
   */
c59ede7b7   Randy.Dunlap   [PATCH] move capa...
24
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
  #include <linux/msg.h>
  #include <linux/spinlock.h>
  #include <linux/init.h>
f7bf3df8b   Nadia Derbey   ipc: scale msgmni...
28
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
34
  #include <linux/proc_fs.h>
  #include <linux/list.h>
  #include <linux/security.h>
  #include <linux/sched.h>
  #include <linux/syscalls.h>
  #include <linux/audit.h>
19b4946ca   Mike Waychison   [PATCH] ipc: conv...
35
  #include <linux/seq_file.h>
3e148c799   Nadia Derbey   fix idr_find() lo...
36
  #include <linux/rwsem.h>
1e7869373   Kirill Korotaev   [PATCH] IPC names...
37
  #include <linux/nsproxy.h>
ae5e1b22f   Pavel Emelyanov   namespaces: move ...
38
  #include <linux/ipc_namespace.h>
5f921ae96   Ingo Molnar   [PATCH] sem2mutex...
39

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <asm/current.h>
7153e4027   Paul McQuade   ipc, kernel: use ...
41
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  #include "util.h"
4bb6657dd   Davidlohr Bueso   ipc,msg: document...
43
  /* one msg_receiver structure for each sleeping receiver */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  struct msg_receiver {
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
45
46
  	struct list_head	r_list;
  	struct task_struct	*r_tsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
48
49
50
  	int			r_mode;
  	long			r_msgtype;
  	long			r_maxsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51

4bb6657dd   Davidlohr Bueso   ipc,msg: document...
52
53
54
55
56
57
  	/*
  	 * Mark r_msg volatile so that the compiler
  	 * does not try to get smart and optimize
  	 * it. We rely on this for the lockless
  	 * receive algorithm.
  	 */
80491eb90   Linus Torvalds   Revert unintentio...
58
  	struct msg_msg		*volatile r_msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
  };
  
  /* one msg_sender for each sleeping sender */
  struct msg_sender {
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
63
64
  	struct list_head	list;
  	struct task_struct	*tsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
67
68
69
70
  };
  
  #define SEARCH_ANY		1
  #define SEARCH_EQUAL		2
  #define SEARCH_NOTEQUAL		3
  #define SEARCH_LESSEQUAL	4
8ac6ed585   Peter Hurley   ipc: implement MS...
71
  #define SEARCH_NUMBER		5
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

ed2ddbf88   Pierre Peiffer   IPC: make struct ...
73
  #define msg_ids(ns)	((ns)->ids[IPC_MSG_IDS])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74

a5001a0d9   Davidlohr Bueso   ipc,msg: introduc...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  static inline struct msg_queue *msq_obtain_object(struct ipc_namespace *ns, int id)
  {
  	struct kern_ipc_perm *ipcp = ipc_obtain_object(&msg_ids(ns), id);
  
  	if (IS_ERR(ipcp))
  		return ERR_CAST(ipcp);
  
  	return container_of(ipcp, struct msg_queue, q_perm);
  }
  
  static inline struct msg_queue *msq_obtain_object_check(struct ipc_namespace *ns,
  							int id)
  {
  	struct kern_ipc_perm *ipcp = ipc_obtain_object_check(&msg_ids(ns), id);
  
  	if (IS_ERR(ipcp))
  		return ERR_CAST(ipcp);
  
  	return container_of(ipcp, struct msg_queue, q_perm);
  }
7ca7e564e   Nadia Derbey   ipc: store ipcs i...
95
96
97
98
  static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
  {
  	ipc_rmid(&msg_ids(ns), &s->q_perm);
  }
53dad6d3a   Davidlohr Bueso   ipc: fix race wit...
99
100
101
102
103
104
105
106
  static void msg_rcu_free(struct rcu_head *head)
  {
  	struct ipc_rcu *p = container_of(head, struct ipc_rcu, rcu);
  	struct msg_queue *msq = ipc_rcu_to_struct(p);
  
  	security_msg_queue_free(msq);
  	ipc_rcu_free(head);
  }
f4566f048   Nadia Derbey   ipc: fix wrong co...
107
108
109
110
111
  /**
   * newque - Create a new msg queue
   * @ns: namespace
   * @params: ptr to the structure that contains the key and msgflg
   *
d9a605e40   Davidlohr Bueso   ipc: rename ids->...
112
   * Called with msg_ids.rwsem held (writer)
f4566f048   Nadia Derbey   ipc: fix wrong co...
113
   */
7748dbfaa   Nadia Derbey   ipc: unify the sy...
114
  static int newque(struct ipc_namespace *ns, struct ipc_params *params)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  	struct msg_queue *msq;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
117
  	int id, retval;
7748dbfaa   Nadia Derbey   ipc: unify the sy...
118
119
  	key_t key = params->key;
  	int msgflg = params->flg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120

5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
121
122
  	msq = ipc_rcu_alloc(sizeof(*msq));
  	if (!msq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  		return -ENOMEM;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
124
  	msq->q_perm.mode = msgflg & S_IRWXUGO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
128
129
  	msq->q_perm.key = key;
  
  	msq->q_perm.security = NULL;
  	retval = security_msg_queue_alloc(msq);
  	if (retval) {
53dad6d3a   Davidlohr Bueso   ipc: fix race wit...
130
  		ipc_rcu_putref(msq, ipc_rcu_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
  		return retval;
  	}
dbfcd91f0   Davidlohr Bueso   ipc: move rcu loc...
133
  	/* ipc_addid() locks msq upon success. */
1e7869373   Kirill Korotaev   [PATCH] IPC names...
134
  	id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
283bb7fad   Pierre Peiffer   IPC: fix error ca...
135
  	if (id < 0) {
53dad6d3a   Davidlohr Bueso   ipc: fix race wit...
136
  		ipc_rcu_putref(msq, msg_rcu_free);
283bb7fad   Pierre Peiffer   IPC: fix error ca...
137
  		return id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
141
142
  	}
  
  	msq->q_stime = msq->q_rtime = 0;
  	msq->q_ctime = get_seconds();
  	msq->q_cbytes = msq->q_qnum = 0;
1e7869373   Kirill Korotaev   [PATCH] IPC names...
143
  	msq->q_qbytes = ns->msg_ctlmnb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
147
  	msq->q_lspid = msq->q_lrpid = 0;
  	INIT_LIST_HEAD(&msq->q_messages);
  	INIT_LIST_HEAD(&msq->q_receivers);
  	INIT_LIST_HEAD(&msq->q_senders);
7ca7e564e   Nadia Derbey   ipc: store ipcs i...
148

cf9d5d78d   Davidlohr Bueso   ipc: close open c...
149
  	ipc_unlock_object(&msq->q_perm);
dbfcd91f0   Davidlohr Bueso   ipc: move rcu loc...
150
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151

7ca7e564e   Nadia Derbey   ipc: store ipcs i...
152
  	return msq->q_perm.id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
154
  static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
  {
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
156
  	mss->tsk = current;
f75a2f358   Davidlohr Bueso   ipc,msg: use curr...
157
  	__set_current_state(TASK_INTERRUPTIBLE);
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
158
  	list_add_tail(&mss->list, &msq->q_senders);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
160
  static inline void ss_del(struct msg_sender *mss)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  {
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
162
  	if (mss->list.next != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
  		list_del(&mss->list);
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
165
  static void ss_wakeup(struct list_head *h, int kill)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  {
41239fe82   Nikola Pajkovsky   ipc/msg.c: use li...
167
  	struct msg_sender *mss, *t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168

41239fe82   Nikola Pajkovsky   ipc/msg.c: use li...
169
  	list_for_each_entry_safe(mss, t, h, list) {
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
170
171
  		if (kill)
  			mss->list.next = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
  		wake_up_process(mss->tsk);
  	}
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
175
  static void expunge_all(struct msg_queue *msq, int res)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  {
41239fe82   Nikola Pajkovsky   ipc/msg.c: use li...
177
  	struct msg_receiver *msr, *t;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
178

41239fe82   Nikola Pajkovsky   ipc/msg.c: use li...
179
  	list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) {
ffa571daf   Davidlohr Bueso   ipc,msg: document...
180
  		msr->r_msg = NULL; /* initialize expunge ordering */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  		wake_up_process(msr->r_tsk);
ffa571daf   Davidlohr Bueso   ipc,msg: document...
182
183
184
185
186
187
  		/*
  		 * Ensure that the wakeup is visible before setting r_msg as
  		 * the receiving end depends on it: either spinning on a nil,
  		 * or dealing with -EAGAIN cases. See lockless receive part 1
  		 * and 2 in do_msgrcv().
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
190
191
  		smp_mb();
  		msr->r_msg = ERR_PTR(res);
  	}
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
192
193
194
  
  /*
   * freeque() wakes up waiters on the sender and receiver waiting queue,
f4566f048   Nadia Derbey   ipc: fix wrong co...
195
196
   * removes the message queue from message queue ID IDR, and cleans up all the
   * messages associated with this queue.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
   *
d9a605e40   Davidlohr Bueso   ipc: rename ids->...
198
199
   * msg_ids.rwsem (writer) and the spinlock for this message queue are held
   * before freeque() is called. msg_ids.rwsem remains locked on exit.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
   */
01b8b07a5   Pierre Peiffer   IPC: consolidate ...
201
  static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  {
41239fe82   Nikola Pajkovsky   ipc/msg.c: use li...
203
  	struct msg_msg *msg, *t;
01b8b07a5   Pierre Peiffer   IPC: consolidate ...
204
  	struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205

5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
206
207
  	expunge_all(msq, -EIDRM);
  	ss_wakeup(&msq->q_senders, 1);
7ca7e564e   Nadia Derbey   ipc: store ipcs i...
208
  	msg_rmid(ns, msq);
4718787d1   Davidlohr Bueso   ipc,msg: drop msg...
209
210
  	ipc_unlock_object(&msq->q_perm);
  	rcu_read_unlock();
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
211

41239fe82   Nikola Pajkovsky   ipc/msg.c: use li...
212
  	list_for_each_entry_safe(msg, t, &msq->q_messages, m_list) {
3ac88a41f   Kirill Korotaev   virtualization of...
213
  		atomic_dec(&ns->msg_hdrs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
  		free_msg(msg);
  	}
3ac88a41f   Kirill Korotaev   virtualization of...
216
  	atomic_sub(msq->q_cbytes, &ns->msg_bytes);
53dad6d3a   Davidlohr Bueso   ipc: fix race wit...
217
  	ipc_rcu_putref(msq, msg_rcu_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  }
f4566f048   Nadia Derbey   ipc: fix wrong co...
219
  /*
d9a605e40   Davidlohr Bueso   ipc: rename ids->...
220
   * Called with msg_ids.rwsem and ipcp locked.
f4566f048   Nadia Derbey   ipc: fix wrong co...
221
   */
03f02c765   Nadia Derbey   Storing ipcs into...
222
  static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
7748dbfaa   Nadia Derbey   ipc: unify the sy...
223
  {
03f02c765   Nadia Derbey   Storing ipcs into...
224
225
226
  	struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
  
  	return security_msg_queue_associate(msq, msgflg);
7748dbfaa   Nadia Derbey   ipc: unify the sy...
227
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
228
  SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  {
1e7869373   Kirill Korotaev   [PATCH] IPC names...
230
  	struct ipc_namespace *ns;
eb66ec44f   Mathias Krause   ipc: constify ipc...
231
232
233
234
  	static const struct ipc_ops msg_ops = {
  		.getnew = newque,
  		.associate = msg_security,
  	};
7748dbfaa   Nadia Derbey   ipc: unify the sy...
235
  	struct ipc_params msg_params;
1e7869373   Kirill Korotaev   [PATCH] IPC names...
236
237
  
  	ns = current->nsproxy->ipc_ns;
7ca7e564e   Nadia Derbey   ipc: store ipcs i...
238

7748dbfaa   Nadia Derbey   ipc: unify the sy...
239
240
  	msg_params.key = key;
  	msg_params.flg = msgflg;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
241

7748dbfaa   Nadia Derbey   ipc: unify the sy...
242
  	return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
244
245
  static inline unsigned long
  copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  {
239521f31   Manfred Spraul   ipc: whitespace c...
247
  	switch (version) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  	case IPC_64:
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
249
  		return copy_to_user(buf, in, sizeof(*in));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  	case IPC_OLD:
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
251
  	{
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
  		struct msqid_ds out;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
253
  		memset(&out, 0, sizeof(out));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
256
257
258
259
  
  		ipc64_perm_to_ipc_perm(&in->msg_perm, &out.msg_perm);
  
  		out.msg_stime		= in->msg_stime;
  		out.msg_rtime		= in->msg_rtime;
  		out.msg_ctime		= in->msg_ctime;
4be929be3   Alexey Dobriyan   kernel-wide: repl...
260
261
  		if (in->msg_cbytes > USHRT_MAX)
  			out.msg_cbytes	= USHRT_MAX;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
  		else
  			out.msg_cbytes	= in->msg_cbytes;
  		out.msg_lcbytes		= in->msg_cbytes;
4be929be3   Alexey Dobriyan   kernel-wide: repl...
265
266
  		if (in->msg_qnum > USHRT_MAX)
  			out.msg_qnum	= USHRT_MAX;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
  		else
  			out.msg_qnum	= in->msg_qnum;
4be929be3   Alexey Dobriyan   kernel-wide: repl...
269
270
  		if (in->msg_qbytes > USHRT_MAX)
  			out.msg_qbytes	= USHRT_MAX;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
274
275
276
  		else
  			out.msg_qbytes	= in->msg_qbytes;
  		out.msg_lqbytes		= in->msg_qbytes;
  
  		out.msg_lspid		= in->msg_lspid;
  		out.msg_lrpid		= in->msg_lrpid;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
277
278
  		return copy_to_user(buf, &out, sizeof(out));
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
281
282
  	default:
  		return -EINVAL;
  	}
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
283
  static inline unsigned long
016d7132f   Pierre Peiffer   IPC: get rid of t...
284
  copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  {
239521f31   Manfred Spraul   ipc: whitespace c...
286
  	switch (version) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  	case IPC_64:
016d7132f   Pierre Peiffer   IPC: get rid of t...
288
  		if (copy_from_user(out, buf, sizeof(*out)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
  			return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
  	case IPC_OLD:
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
292
  	{
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  		struct msqid_ds tbuf_old;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
294
  		if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  			return -EFAULT;
239521f31   Manfred Spraul   ipc: whitespace c...
296
297
298
  		out->msg_perm.uid	= tbuf_old.msg_perm.uid;
  		out->msg_perm.gid	= tbuf_old.msg_perm.gid;
  		out->msg_perm.mode	= tbuf_old.msg_perm.mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299

5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
300
  		if (tbuf_old.msg_qbytes == 0)
016d7132f   Pierre Peiffer   IPC: get rid of t...
301
  			out->msg_qbytes	= tbuf_old.msg_lqbytes;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
  		else
016d7132f   Pierre Peiffer   IPC: get rid of t...
303
  			out->msg_qbytes	= tbuf_old.msg_qbytes;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
  
  		return 0;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
306
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
310
  	default:
  		return -EINVAL;
  	}
  }
a0d092fc2   Pierre Peiffer   IPC/message queue...
311
  /*
d9a605e40   Davidlohr Bueso   ipc: rename ids->...
312
   * This function handles some msgctl commands which require the rwsem
a0d092fc2   Pierre Peiffer   IPC/message queue...
313
   * to be held in write mode.
d9a605e40   Davidlohr Bueso   ipc: rename ids->...
314
   * NOTE: no locks must be held, the rwsem is taken inside this function.
a0d092fc2   Pierre Peiffer   IPC/message queue...
315
316
317
   */
  static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
  		       struct msqid_ds __user *buf, int version)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  	struct kern_ipc_perm *ipcp;
f1970c48e   Felipe Contreras   ipc: fix unused v...
320
  	struct msqid64_ds uninitialized_var(msqid64);
a0d092fc2   Pierre Peiffer   IPC/message queue...
321
322
323
324
  	struct msg_queue *msq;
  	int err;
  
  	if (cmd == IPC_SET) {
016d7132f   Pierre Peiffer   IPC: get rid of t...
325
  		if (copy_msqid_from_user(&msqid64, buf, version))
a0d092fc2   Pierre Peiffer   IPC/message queue...
326
327
  			return -EFAULT;
  	}
d9a605e40   Davidlohr Bueso   ipc: rename ids->...
328
  	down_write(&msg_ids(ns).rwsem);
7b4cc5d84   Davidlohr Bueso   ipc: move locking...
329
  	rcu_read_lock();
15724ecb7   Davidlohr Bueso   ipc,msg: shorten ...
330
331
  	ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd,
  				      &msqid64.msg_perm, msqid64.msg_qbytes);
7b4cc5d84   Davidlohr Bueso   ipc: move locking...
332
333
  	if (IS_ERR(ipcp)) {
  		err = PTR_ERR(ipcp);
7b4cc5d84   Davidlohr Bueso   ipc: move locking...
334
335
  		goto out_unlock1;
  	}
a0d092fc2   Pierre Peiffer   IPC/message queue...
336

a5f75e7f2   Pierre Peiffer   IPC: consolidate ...
337
  	msq = container_of(ipcp, struct msg_queue, q_perm);
a0d092fc2   Pierre Peiffer   IPC/message queue...
338
339
340
  
  	err = security_msg_queue_msgctl(msq, cmd);
  	if (err)
15724ecb7   Davidlohr Bueso   ipc,msg: shorten ...
341
  		goto out_unlock1;
a0d092fc2   Pierre Peiffer   IPC/message queue...
342
343
344
  
  	switch (cmd) {
  	case IPC_RMID:
15724ecb7   Davidlohr Bueso   ipc,msg: shorten ...
345
  		ipc_lock_object(&msq->q_perm);
7b4cc5d84   Davidlohr Bueso   ipc: move locking...
346
  		/* freeque unlocks the ipc object and rcu */
a0d092fc2   Pierre Peiffer   IPC/message queue...
347
348
349
  		freeque(ns, ipcp);
  		goto out_up;
  	case IPC_SET:
016d7132f   Pierre Peiffer   IPC: get rid of t...
350
  		if (msqid64.msg_qbytes > ns->msg_ctlmnb &&
a0d092fc2   Pierre Peiffer   IPC/message queue...
351
352
  		    !capable(CAP_SYS_RESOURCE)) {
  			err = -EPERM;
15724ecb7   Davidlohr Bueso   ipc,msg: shorten ...
353
  			goto out_unlock1;
a0d092fc2   Pierre Peiffer   IPC/message queue...
354
  		}
15724ecb7   Davidlohr Bueso   ipc,msg: shorten ...
355
  		ipc_lock_object(&msq->q_perm);
1efdb69b0   Eric W. Biederman   userns: Convert i...
356
357
  		err = ipc_update_perm(&msqid64.msg_perm, ipcp);
  		if (err)
7b4cc5d84   Davidlohr Bueso   ipc: move locking...
358
  			goto out_unlock0;
1efdb69b0   Eric W. Biederman   userns: Convert i...
359

016d7132f   Pierre Peiffer   IPC: get rid of t...
360
  		msq->q_qbytes = msqid64.msg_qbytes;
a0d092fc2   Pierre Peiffer   IPC/message queue...
361

a0d092fc2   Pierre Peiffer   IPC/message queue...
362
363
364
365
366
367
368
369
370
371
372
373
  		msq->q_ctime = get_seconds();
  		/* sleeping receivers might be excluded by
  		 * stricter permissions.
  		 */
  		expunge_all(msq, -EAGAIN);
  		/* sleeping senders might be able to send
  		 * due to a larger queue size.
  		 */
  		ss_wakeup(&msq->q_senders, 0);
  		break;
  	default:
  		err = -EINVAL;
15724ecb7   Davidlohr Bueso   ipc,msg: shorten ...
374
  		goto out_unlock1;
a0d092fc2   Pierre Peiffer   IPC/message queue...
375
  	}
7b4cc5d84   Davidlohr Bueso   ipc: move locking...
376
377
378
379
380
  
  out_unlock0:
  	ipc_unlock_object(&msq->q_perm);
  out_unlock1:
  	rcu_read_unlock();
a0d092fc2   Pierre Peiffer   IPC/message queue...
381
  out_up:
d9a605e40   Davidlohr Bueso   ipc: rename ids->...
382
  	up_write(&msg_ids(ns).rwsem);
a0d092fc2   Pierre Peiffer   IPC/message queue...
383
384
  	return err;
  }
2cafed30f   Davidlohr Bueso   ipc,msg: introduc...
385
386
  static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
  			 int cmd, int version, void __user *buf)
a0d092fc2   Pierre Peiffer   IPC/message queue...
387
  {
2cafed30f   Davidlohr Bueso   ipc,msg: introduc...
388
  	int err;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
389
  	struct msg_queue *msq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
  
  	switch (cmd) {
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
392
393
394
  	case IPC_INFO:
  	case MSG_INFO:
  	{
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
  		struct msginfo msginfo;
  		int max_id;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
397

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
  		if (!buf)
  			return -EFAULT;
2cafed30f   Davidlohr Bueso   ipc,msg: introduc...
400

5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
401
402
  		/*
  		 * We must not return kernel stack data.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
  		 * due to padding, it's not enough
  		 * to set all member fields.
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
  		err = security_msg_queue_msgctl(NULL, cmd);
  		if (err)
  			return err;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
409
  		memset(&msginfo, 0, sizeof(msginfo));
1e7869373   Kirill Korotaev   [PATCH] IPC names...
410
411
412
  		msginfo.msgmni = ns->msg_ctlmni;
  		msginfo.msgmax = ns->msg_ctlmax;
  		msginfo.msgmnb = ns->msg_ctlmnb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
  		msginfo.msgssz = MSGSSZ;
  		msginfo.msgseg = MSGSEG;
d9a605e40   Davidlohr Bueso   ipc: rename ids->...
415
  		down_read(&msg_ids(ns).rwsem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
  		if (cmd == MSG_INFO) {
1e7869373   Kirill Korotaev   [PATCH] IPC names...
417
  			msginfo.msgpool = msg_ids(ns).in_use;
3ac88a41f   Kirill Korotaev   virtualization of...
418
419
  			msginfo.msgmap = atomic_read(&ns->msg_hdrs);
  			msginfo.msgtql = atomic_read(&ns->msg_bytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
424
  		} else {
  			msginfo.msgmap = MSGMAP;
  			msginfo.msgpool = MSGPOOL;
  			msginfo.msgtql = MSGTQL;
  		}
7ca7e564e   Nadia Derbey   ipc: store ipcs i...
425
  		max_id = ipc_get_maxid(&msg_ids(ns));
d9a605e40   Davidlohr Bueso   ipc: rename ids->...
426
  		up_read(&msg_ids(ns).rwsem);
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
427
  		if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  			return -EFAULT;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
429
  		return (max_id < 0) ? 0 : max_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
  	}
2cafed30f   Davidlohr Bueso   ipc,msg: introduc...
431
432
  
  	case MSG_STAT:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
  	case IPC_STAT:
  	{
  		struct msqid64_ds tbuf;
  		int success_return;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
437

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
  		if (!buf)
  			return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440

ac0ba20ea   Davidlohr Bueso   ipc,msg: make msg...
441
442
443
  		memset(&tbuf, 0, sizeof(tbuf));
  
  		rcu_read_lock();
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
444
  		if (cmd == MSG_STAT) {
ac0ba20ea   Davidlohr Bueso   ipc,msg: make msg...
445
446
447
448
449
  			msq = msq_obtain_object(ns, msqid);
  			if (IS_ERR(msq)) {
  				err = PTR_ERR(msq);
  				goto out_unlock;
  			}
7ca7e564e   Nadia Derbey   ipc: store ipcs i...
450
  			success_return = msq->q_perm.id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
  		} else {
ac0ba20ea   Davidlohr Bueso   ipc,msg: make msg...
452
453
454
455
456
  			msq = msq_obtain_object_check(ns, msqid);
  			if (IS_ERR(msq)) {
  				err = PTR_ERR(msq);
  				goto out_unlock;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
  			success_return = 0;
  		}
ac0ba20ea   Davidlohr Bueso   ipc,msg: make msg...
459

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  		err = -EACCES;
b0e77598f   Serge E. Hallyn   userns: user name...
461
  		if (ipcperms(ns, &msq->q_perm, S_IRUGO))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
  			goto out_unlock;
  
  		err = security_msg_queue_msgctl(msq, cmd);
  		if (err)
  			goto out_unlock;
  
  		kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
  		tbuf.msg_stime  = msq->q_stime;
  		tbuf.msg_rtime  = msq->q_rtime;
  		tbuf.msg_ctime  = msq->q_ctime;
  		tbuf.msg_cbytes = msq->q_cbytes;
  		tbuf.msg_qnum   = msq->q_qnum;
  		tbuf.msg_qbytes = msq->q_qbytes;
  		tbuf.msg_lspid  = msq->q_lspid;
  		tbuf.msg_lrpid  = msq->q_lrpid;
ac0ba20ea   Davidlohr Bueso   ipc,msg: make msg...
477
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
481
  		if (copy_msqid_to_user(buf, &tbuf, version))
  			return -EFAULT;
  		return success_return;
  	}
2cafed30f   Davidlohr Bueso   ipc,msg: introduc...
482

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
  	default:
2cafed30f   Davidlohr Bueso   ipc,msg: introduc...
484
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
  	}
2cafed30f   Davidlohr Bueso   ipc,msg: introduc...
486
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  out_unlock:
ac0ba20ea   Davidlohr Bueso   ipc,msg: make msg...
488
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
490
  	return err;
  }
2cafed30f   Davidlohr Bueso   ipc,msg: introduc...
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
  SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
  {
  	int version;
  	struct ipc_namespace *ns;
  
  	if (msqid < 0 || cmd < 0)
  		return -EINVAL;
  
  	version = ipc_parse_version(&cmd);
  	ns = current->nsproxy->ipc_ns;
  
  	switch (cmd) {
  	case IPC_INFO:
  	case MSG_INFO:
  	case MSG_STAT:	/* msqid is an index rather than a msg queue id */
  	case IPC_STAT:
  		return msgctl_nolock(ns, msqid, cmd, version, buf);
  	case IPC_SET:
  	case IPC_RMID:
  		return msgctl_down(ns, msqid, cmd, buf, version);
  	default:
  		return  -EINVAL;
  	}
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
515
  static int testmsg(struct msg_msg *msg, long type, int mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
  {
46c0a8ca3   Paul McQuade   ipc, kernel: clea...
517
518
519
520
521
522
523
524
525
526
  	switch (mode) {
  	case SEARCH_ANY:
  	case SEARCH_NUMBER:
  		return 1;
  	case SEARCH_LESSEQUAL:
  		if (msg->m_type <= type)
  			return 1;
  		break;
  	case SEARCH_EQUAL:
  		if (msg->m_type == type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  			return 1;
46c0a8ca3   Paul McQuade   ipc, kernel: clea...
528
529
530
531
532
  		break;
  	case SEARCH_NOTEQUAL:
  		if (msg->m_type != type)
  			return 1;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
535
  	}
  	return 0;
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
536
  static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
  {
41239fe82   Nikola Pajkovsky   ipc/msg.c: use li...
538
  	struct msg_receiver *msr, *t;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
539

41239fe82   Nikola Pajkovsky   ipc/msg.c: use li...
540
  	list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) {
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
541
542
543
  		if (testmsg(msg, msr->r_msgtype, msr->r_mode) &&
  		    !security_msg_queue_msgrcv(msq, msg, msr->r_tsk,
  					       msr->r_msgtype, msr->r_mode)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
  			list_del(&msr->r_list);
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
545
  			if (msr->r_maxsize < msg->m_ts) {
ffa571daf   Davidlohr Bueso   ipc,msg: document...
546
  				/* initialize pipelined send ordering */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
  				msr->r_msg = NULL;
  				wake_up_process(msr->r_tsk);
ffa571daf   Davidlohr Bueso   ipc,msg: document...
549
  				smp_mb(); /* see barrier comment below */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
552
  				msr->r_msg = ERR_PTR(-E2BIG);
  			} else {
  				msr->r_msg = NULL;
b488893a3   Pavel Emelyanov   pid namespaces: c...
553
  				msq->q_lrpid = task_pid_vnr(msr->r_tsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
  				msq->q_rtime = get_seconds();
  				wake_up_process(msr->r_tsk);
ffa571daf   Davidlohr Bueso   ipc,msg: document...
556
557
558
559
560
561
  				/*
  				 * Ensure that the wakeup is visible before
  				 * setting r_msg, as the receiving end depends
  				 * on it. See lockless receive part 1 and 2 in
  				 * do_msgrcv().
  				 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
  				smp_mb();
  				msr->r_msg = msg;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
564

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
566
567
568
  				return 1;
  			}
  		}
  	}
ffa571daf   Davidlohr Bueso   ipc,msg: document...
569

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
571
  	return 0;
  }
651971cb7   suzuki   [PATCH] Fix the s...
572
573
  long do_msgsnd(int msqid, long mtype, void __user *mtext,
  		size_t msgsz, int msgflg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
575
576
  {
  	struct msg_queue *msq;
  	struct msg_msg *msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
  	int err;
1e7869373   Kirill Korotaev   [PATCH] IPC names...
578
579
580
  	struct ipc_namespace *ns;
  
  	ns = current->nsproxy->ipc_ns;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
581

1e7869373   Kirill Korotaev   [PATCH] IPC names...
582
  	if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
585
  	if (mtype < 1)
  		return -EINVAL;
651971cb7   suzuki   [PATCH] Fix the s...
586
  	msg = load_msg(mtext, msgsz);
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
587
  	if (IS_ERR(msg))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
589
590
591
  		return PTR_ERR(msg);
  
  	msg->m_type = mtype;
  	msg->m_ts = msgsz;
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
592
593
  	rcu_read_lock();
  	msq = msq_obtain_object_check(ns, msqid);
023a53557   Nadia Derbey   ipc: integrate ip...
594
595
  	if (IS_ERR(msq)) {
  		err = PTR_ERR(msq);
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
596
  		goto out_unlock1;
023a53557   Nadia Derbey   ipc: integrate ip...
597
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598

bebcb928c   Manfred Spraul   ipc/msg.c: Fix lo...
599
  	ipc_lock_object(&msq->q_perm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
601
  	for (;;) {
  		struct msg_sender s;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
602
  		err = -EACCES;
b0e77598f   Serge E. Hallyn   userns: user name...
603
  		if (ipcperms(ns, &msq->q_perm, S_IWUGO))
bebcb928c   Manfred Spraul   ipc/msg.c: Fix lo...
604
  			goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605

4271b05a2   Davidlohr Bueso   ipc,msg: prevent ...
606
  		/* raced with RMID? */
0f3d2b013   Rafael Aquini   ipc: introduce ip...
607
  		if (!ipc_valid_object(&msq->q_perm)) {
4271b05a2   Davidlohr Bueso   ipc,msg: prevent ...
608
609
610
  			err = -EIDRM;
  			goto out_unlock0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
612
  		err = security_msg_queue_msgsnd(msq, msg, msgflg);
  		if (err)
bebcb928c   Manfred Spraul   ipc/msg.c: Fix lo...
613
  			goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614

5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
615
  		if (msgsz + msq->q_cbytes <= msq->q_qbytes &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
617
618
619
620
  				1 + msq->q_qnum <= msq->q_qbytes) {
  			break;
  		}
  
  		/* queue full, wait: */
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
621
622
  		if (msgflg & IPC_NOWAIT) {
  			err = -EAGAIN;
bebcb928c   Manfred Spraul   ipc/msg.c: Fix lo...
623
  			goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
  		}
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
625

ffa571daf   Davidlohr Bueso   ipc,msg: document...
626
  		/* enqueue the sender and prepare to block */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  		ss_add(msq, &s);
6062a8dc0   Rik van Riel   ipc,sem: fine gra...
628
629
630
  
  		if (!ipc_rcu_getref(msq)) {
  			err = -EIDRM;
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
631
  			goto out_unlock0;
6062a8dc0   Rik van Riel   ipc,sem: fine gra...
632
  		}
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
633
634
  		ipc_unlock_object(&msq->q_perm);
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
  		schedule();
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
636
637
  		rcu_read_lock();
  		ipc_lock_object(&msq->q_perm);
53dad6d3a   Davidlohr Bueso   ipc: fix race wit...
638
  		ipc_rcu_putref(msq, ipc_rcu_free);
0f3d2b013   Rafael Aquini   ipc: introduce ip...
639
640
  		/* raced with RMID? */
  		if (!ipc_valid_object(&msq->q_perm)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641
  			err = -EIDRM;
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
642
  			goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
  		}
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
644

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
  		ss_del(&s);
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
646

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
  		if (signal_pending(current)) {
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
648
  			err = -ERESTARTNOHAND;
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
649
  			goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  		}
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
651

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  	}
b488893a3   Pavel Emelyanov   pid namespaces: c...
653
  	msq->q_lspid = task_tgid_vnr(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  	msq->q_stime = get_seconds();
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
655
  	if (!pipelined_send(msq, msg)) {
25985edce   Lucas De Marchi   Fix common misspe...
656
  		/* no one is waiting for this message, enqueue it */
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
657
  		list_add_tail(&msg->m_list, &msq->q_messages);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
  		msq->q_cbytes += msgsz;
  		msq->q_qnum++;
3ac88a41f   Kirill Korotaev   virtualization of...
660
661
  		atomic_add(msgsz, &ns->msg_bytes);
  		atomic_inc(&ns->msg_hdrs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
  	}
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
663

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
665
  	err = 0;
  	msg = NULL;
3dd1f784e   Davidlohr Bueso   ipc,msg: shorten ...
666
667
668
669
  out_unlock0:
  	ipc_unlock_object(&msq->q_perm);
  out_unlock1:
  	rcu_read_unlock();
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
670
  	if (msg != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
673
  		free_msg(msg);
  	return err;
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
674
675
  SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
  		int, msgflg)
651971cb7   suzuki   [PATCH] Fix the s...
676
677
678
679
680
681
682
  {
  	long mtype;
  
  	if (get_user(mtype, &msgp->mtype))
  		return -EFAULT;
  	return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
  }
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
683
  static inline int convert_mode(long *msgtyp, int msgflg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
  {
8ac6ed585   Peter Hurley   ipc: implement MS...
685
686
  	if (msgflg & MSG_COPY)
  		return SEARCH_NUMBER;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
687
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
690
  	 *  find message of correct type.
  	 *  msgtyp = 0 => get first.
  	 *  msgtyp > 0 => get first message of matching type.
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
691
  	 *  msgtyp < 0 => get message with least type must be < abs(msgtype).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
  	 */
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
693
  	if (*msgtyp == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
  		return SEARCH_ANY;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
695
696
  	if (*msgtyp < 0) {
  		*msgtyp = -*msgtyp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
698
  		return SEARCH_LESSEQUAL;
  	}
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
699
  	if (msgflg & MSG_EXCEPT)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
701
702
  		return SEARCH_NOTEQUAL;
  	return SEARCH_EQUAL;
  }
f9dd87f47   Stanislav Kinsbursky   ipc: message queu...
703
704
705
706
707
708
709
710
711
712
713
714
715
  static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
  {
  	struct msgbuf __user *msgp = dest;
  	size_t msgsz;
  
  	if (put_user(msg->m_type, &msgp->mtype))
  		return -EFAULT;
  
  	msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
  	if (store_msg(msgp->mtext, msg, msgsz))
  		return -EFAULT;
  	return msgsz;
  }
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
716
  #ifdef CONFIG_CHECKPOINT_RESTORE
3fcfe7865   Stanislav Kinsbursky   ipc: add more com...
717
718
719
720
  /*
   * This function creates new kernel message structure, large enough to store
   * bufsz message bytes.
   */
8ac6ed585   Peter Hurley   ipc: implement MS...
721
  static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
722
723
  {
  	struct msg_msg *copy;
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
724
725
726
727
728
729
730
731
  	/*
  	 * Create dummy message to copy real message to.
  	 */
  	copy = load_msg(buf, bufsz);
  	if (!IS_ERR(copy))
  		copy->m_ts = bufsz;
  	return copy;
  }
85398aa8d   Stanislav Kinsbursky   ipc: simplify fre...
732
  static inline void free_copy(struct msg_msg *copy)
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
733
  {
85398aa8d   Stanislav Kinsbursky   ipc: simplify fre...
734
  	if (copy)
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
735
736
737
  		free_msg(copy);
  }
  #else
8ac6ed585   Peter Hurley   ipc: implement MS...
738
  static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
b30efe277   Stanislav Kinsbursky   ipc: convert prep...
739
740
741
  {
  	return ERR_PTR(-ENOSYS);
  }
85398aa8d   Stanislav Kinsbursky   ipc: simplify fre...
742
743
744
  static inline void free_copy(struct msg_msg *copy)
  {
  }
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
745
  #endif
daaf74cf0   Peter Hurley   ipc: refactor msg...
746
747
  static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
  {
368ae537e   Svenning Sørensen   IPC: bugfix for m...
748
  	struct msg_msg *msg, *found = NULL;
daaf74cf0   Peter Hurley   ipc: refactor msg...
749
750
751
752
753
754
755
756
  	long count = 0;
  
  	list_for_each_entry(msg, &msq->q_messages, m_list) {
  		if (testmsg(msg, *msgtyp, mode) &&
  		    !security_msg_queue_msgrcv(msq, msg, current,
  					       *msgtyp, mode)) {
  			if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
  				*msgtyp = msg->m_type - 1;
368ae537e   Svenning Sørensen   IPC: bugfix for m...
757
  				found = msg;
daaf74cf0   Peter Hurley   ipc: refactor msg...
758
759
760
761
762
763
764
765
  			} else if (mode == SEARCH_NUMBER) {
  				if (*msgtyp == count)
  					return msg;
  			} else
  				return msg;
  			count++;
  		}
  	}
368ae537e   Svenning Sørensen   IPC: bugfix for m...
766
  	return found ?: ERR_PTR(-EAGAIN);
daaf74cf0   Peter Hurley   ipc: refactor msg...
767
  }
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
768
  long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg,
f9dd87f47   Stanislav Kinsbursky   ipc: message queu...
769
  	       long (*msg_handler)(void __user *, struct msg_msg *, size_t))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
  	int mode;
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
772
  	struct msg_queue *msq;
1e7869373   Kirill Korotaev   [PATCH] IPC names...
773
  	struct ipc_namespace *ns;
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
774
  	struct msg_msg *msg, *copy = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775

88b9e456b   Peter Hurley   ipc: don't alloca...
776
  	ns = current->nsproxy->ipc_ns;
f9dd87f47   Stanislav Kinsbursky   ipc: message queu...
777
  	if (msqid < 0 || (long) bufsz < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
  		return -EINVAL;
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
779

4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
780
  	if (msgflg & MSG_COPY) {
4f87dac38   Michael Kerrisk   ipc: Fix 2 bugs i...
781
782
  		if ((msgflg & MSG_EXCEPT) || !(msgflg & IPC_NOWAIT))
  			return -EINVAL;
8ac6ed585   Peter Hurley   ipc: implement MS...
783
  		copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax));
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
784
785
786
  		if (IS_ERR(copy))
  			return PTR_ERR(copy);
  	}
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
787
  	mode = convert_mode(&msgtyp, msgflg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788

41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
789
790
  	rcu_read_lock();
  	msq = msq_obtain_object_check(ns, msqid);
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
791
  	if (IS_ERR(msq)) {
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
792
  		rcu_read_unlock();
85398aa8d   Stanislav Kinsbursky   ipc: simplify fre...
793
  		free_copy(copy);
023a53557   Nadia Derbey   ipc: integrate ip...
794
  		return PTR_ERR(msq);
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
795
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
797
798
  
  	for (;;) {
  		struct msg_receiver msr_d;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
800
  
  		msg = ERR_PTR(-EACCES);
b0e77598f   Serge E. Hallyn   userns: user name...
801
  		if (ipcperms(ns, &msq->q_perm, S_IRUGO))
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
802
  			goto out_unlock1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803

41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
804
  		ipc_lock_object(&msq->q_perm);
4271b05a2   Davidlohr Bueso   ipc,msg: prevent ...
805
806
  
  		/* raced with RMID? */
0f3d2b013   Rafael Aquini   ipc: introduce ip...
807
  		if (!ipc_valid_object(&msq->q_perm)) {
4271b05a2   Davidlohr Bueso   ipc,msg: prevent ...
808
809
810
  			msg = ERR_PTR(-EIDRM);
  			goto out_unlock0;
  		}
daaf74cf0   Peter Hurley   ipc: refactor msg...
811
  		msg = find_msg(msq, &msgtyp, mode);
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
812
813
814
815
816
  		if (!IS_ERR(msg)) {
  			/*
  			 * Found a suitable message.
  			 * Unlink it from the queue.
  			 */
f9dd87f47   Stanislav Kinsbursky   ipc: message queu...
817
  			if ((bufsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818
  				msg = ERR_PTR(-E2BIG);
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
819
  				goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
  			}
3fcfe7865   Stanislav Kinsbursky   ipc: add more com...
821
822
823
824
  			/*
  			 * If we are copying, then do not unlink message and do
  			 * not update queue parameters.
  			 */
852028af8   Peter Hurley   ipc: remove msg h...
825
826
  			if (msgflg & MSG_COPY) {
  				msg = copy_msg(msg, copy);
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
827
  				goto out_unlock0;
852028af8   Peter Hurley   ipc: remove msg h...
828
  			}
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
829

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
831
832
  			list_del(&msg->m_list);
  			msq->q_qnum--;
  			msq->q_rtime = get_seconds();
b488893a3   Pavel Emelyanov   pid namespaces: c...
833
  			msq->q_lrpid = task_tgid_vnr(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
  			msq->q_cbytes -= msg->m_ts;
3ac88a41f   Kirill Korotaev   virtualization of...
835
836
  			atomic_sub(msg->m_ts, &ns->msg_bytes);
  			atomic_dec(&ns->msg_hdrs);
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
837
  			ss_wakeup(&msq->q_senders, 0);
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
838
839
  
  			goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
  		}
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
841

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842
843
844
  		/* No message waiting. Wait for a message */
  		if (msgflg & IPC_NOWAIT) {
  			msg = ERR_PTR(-ENOMSG);
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
845
  			goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
  		}
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
847

5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
848
  		list_add_tail(&msr_d.r_list, &msq->q_receivers);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
850
851
  		msr_d.r_tsk = current;
  		msr_d.r_msgtype = msgtyp;
  		msr_d.r_mode = mode;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
852
  		if (msgflg & MSG_NOERROR)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853
  			msr_d.r_maxsize = INT_MAX;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
854
  		else
f9dd87f47   Stanislav Kinsbursky   ipc: message queu...
855
  			msr_d.r_maxsize = bufsz;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
  		msr_d.r_msg = ERR_PTR(-EAGAIN);
f75a2f358   Davidlohr Bueso   ipc,msg: use curr...
857
  		__set_current_state(TASK_INTERRUPTIBLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858

41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
859
860
  		ipc_unlock_object(&msq->q_perm);
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
862
863
864
865
866
  		schedule();
  
  		/* Lockless receive, part 1:
  		 * Disable preemption.  We don't hold a reference to the queue
  		 * and getting a reference would defeat the idea of a lockless
  		 * operation, thus the code relies on rcu to guarantee the
25985edce   Lucas De Marchi   Fix common misspe...
867
  		 * existence of msq:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
869
870
  		 * Prior to destruction, expunge_all(-EIRDM) changes r_msg.
  		 * Thus if r_msg is -EAGAIN, then the queue not yet destroyed.
  		 * rcu_read_lock() prevents preemption between reading r_msg
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
871
  		 * and acquiring the q_perm.lock in ipc_lock_object().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
874
875
876
877
878
879
  		 */
  		rcu_read_lock();
  
  		/* Lockless receive, part 2:
  		 * Wait until pipelined_send or expunge_all are outside of
  		 * wake_up_process(). There is a race with exit(), see
  		 * ipc/mqueue.c for the details.
  		 */
239521f31   Manfred Spraul   ipc: whitespace c...
880
  		msg = (struct msg_msg *)msr_d.r_msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
882
  		while (msg == NULL) {
  			cpu_relax();
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
883
  			msg = (struct msg_msg *)msr_d.r_msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
885
886
887
888
889
  		}
  
  		/* Lockless receive, part 3:
  		 * If there is a message or an error then accept it without
  		 * locking.
  		 */
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
890
891
  		if (msg != ERR_PTR(-EAGAIN))
  			goto out_unlock1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
893
894
895
  
  		/* Lockless receive, part 3:
  		 * Acquire the queue spinlock.
  		 */
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
896
  		ipc_lock_object(&msq->q_perm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
  
  		/* Lockless receive, part 4:
  		 * Repeat test after acquiring the spinlock.
  		 */
239521f31   Manfred Spraul   ipc: whitespace c...
901
  		msg = (struct msg_msg *)msr_d.r_msg;
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
902
  		if (msg != ERR_PTR(-EAGAIN))
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
903
  			goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
905
906
907
  
  		list_del(&msr_d.r_list);
  		if (signal_pending(current)) {
  			msg = ERR_PTR(-ERESTARTNOHAND);
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
908
  			goto out_unlock0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909
  		}
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
910
911
  
  		ipc_unlock_object(&msq->q_perm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
  	}
41a0d523d   Davidlohr Bueso   ipc,msg: shorten ...
913
914
915
916
917
  
  out_unlock0:
  	ipc_unlock_object(&msq->q_perm);
  out_unlock1:
  	rcu_read_unlock();
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
918
  	if (IS_ERR(msg)) {
85398aa8d   Stanislav Kinsbursky   ipc: simplify fre...
919
  		free_copy(copy);
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
920
  		return PTR_ERR(msg);
4a674f34b   Stanislav Kinsbursky   ipc: introduce me...
921
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922

f9dd87f47   Stanislav Kinsbursky   ipc: message queu...
923
  	bufsz = msg_handler(buf, msg, bufsz);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
  	free_msg(msg);
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
925

f9dd87f47   Stanislav Kinsbursky   ipc: message queu...
926
  	return bufsz;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
928
929
  SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
  		long, msgtyp, int, msgflg)
651971cb7   suzuki   [PATCH] Fix the s...
930
  {
f9dd87f47   Stanislav Kinsbursky   ipc: message queu...
931
  	return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
651971cb7   suzuki   [PATCH] Fix the s...
932
  }
3440a6bd1   Davidlohr Bueso   ipc,msg: move som...
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
  /*
   * Scale msgmni with the available lowmem size: the memory dedicated to msg
   * queues should occupy at most 1/MSG_MEM_SCALE of lowmem.
   * Also take into account the number of nsproxies created so far.
   * This should be done staying within the (MSGMNI , IPCMNI/nr_ipc_ns) range.
   */
  void recompute_msgmni(struct ipc_namespace *ns)
  {
  	struct sysinfo i;
  	unsigned long allowed;
  	int nb_ns;
  
  	si_meminfo(&i);
  	allowed = (((i.totalram - i.totalhigh) / MSG_MEM_SCALE) * i.mem_unit)
  		/ MSGMNB;
  	nb_ns = atomic_read(&nr_ipc_ns);
  	allowed /= nb_ns;
  
  	if (allowed < MSGMNI) {
  		ns->msg_ctlmni = MSGMNI;
  		return;
  	}
  
  	if (allowed > IPCMNI / nb_ns) {
  		ns->msg_ctlmni = IPCMNI / nb_ns;
  		return;
  	}
  
  	ns->msg_ctlmni = allowed;
  }
  
  void msg_init_ns(struct ipc_namespace *ns)
  {
  	ns->msg_ctlmax = MSGMAX;
  	ns->msg_ctlmnb = MSGMNB;
  
  	recompute_msgmni(ns);
  
  	atomic_set(&ns->msg_bytes, 0);
  	atomic_set(&ns->msg_hdrs, 0);
  	ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
  }
  
  #ifdef CONFIG_IPC_NS
  void msg_exit_ns(struct ipc_namespace *ns)
  {
  	free_ipcs(ns, &msg_ids(ns), freeque);
  	idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr);
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
  #ifdef CONFIG_PROC_FS
19b4946ca   Mike Waychison   [PATCH] ipc: conv...
984
  static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
  {
1efdb69b0   Eric W. Biederman   userns: Convert i...
986
  	struct user_namespace *user_ns = seq_user_ns(s);
19b4946ca   Mike Waychison   [PATCH] ipc: conv...
987
988
989
  	struct msg_queue *msq = it;
  
  	return seq_printf(s,
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
990
991
992
  			"%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu
  ",
  			msq->q_perm.key,
7ca7e564e   Nadia Derbey   ipc: store ipcs i...
993
  			msq->q_perm.id,
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
994
995
996
997
998
  			msq->q_perm.mode,
  			msq->q_cbytes,
  			msq->q_qnum,
  			msq->q_lspid,
  			msq->q_lrpid,
1efdb69b0   Eric W. Biederman   userns: Convert i...
999
1000
1001
1002
  			from_kuid_munged(user_ns, msq->q_perm.uid),
  			from_kgid_munged(user_ns, msq->q_perm.gid),
  			from_kuid_munged(user_ns, msq->q_perm.cuid),
  			from_kgid_munged(user_ns, msq->q_perm.cgid),
5a06a363e   Ingo Molnar   [PATCH] ipc/msg.c...
1003
1004
1005
  			msq->q_stime,
  			msq->q_rtime,
  			msq->q_ctime);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
1007
  }
  #endif
3440a6bd1   Davidlohr Bueso   ipc,msg: move som...
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
  
  void __init msg_init(void)
  {
  	msg_init_ns(&init_ipc_ns);
  
  	printk(KERN_INFO "msgmni has been set to %d
  ",
  		init_ipc_ns.msg_ctlmni);
  
  	ipc_init_proc_interface("sysvipc/msg",
  				"       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime
  ",
  				IPC_MSG_IDS, sysvipc_msg_proc_show);
  }