diff options
Diffstat (limited to 'ipc/msg.c')
-rw-r--r-- | ipc/msg.c | 253 |
1 files changed, 140 insertions, 113 deletions
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/syscalls.h> | 34 | #include <linux/syscalls.h> |
35 | #include <linux/audit.h> | 35 | #include <linux/audit.h> |
36 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
37 | #include <linux/mutex.h> | 37 | #include <linux/rwsem.h> |
38 | #include <linux/nsproxy.h> | 38 | #include <linux/nsproxy.h> |
39 | 39 | ||
40 | #include <asm/current.h> | 40 | #include <asm/current.h> |
@@ -66,23 +66,15 @@ struct msg_sender { | |||
66 | #define SEARCH_NOTEQUAL 3 | 66 | #define SEARCH_NOTEQUAL 3 |
67 | #define SEARCH_LESSEQUAL 4 | 67 | #define SEARCH_LESSEQUAL 4 |
68 | 68 | ||
69 | static atomic_t msg_bytes = ATOMIC_INIT(0); | ||
70 | static atomic_t msg_hdrs = ATOMIC_INIT(0); | ||
71 | |||
72 | static struct ipc_ids init_msg_ids; | 69 | static struct ipc_ids init_msg_ids; |
73 | 70 | ||
74 | #define msg_ids(ns) (*((ns)->ids[IPC_MSG_IDS])) | 71 | #define msg_ids(ns) (*((ns)->ids[IPC_MSG_IDS])) |
75 | 72 | ||
76 | #define msg_lock(ns, id) ((struct msg_queue*)ipc_lock(&msg_ids(ns), id)) | ||
77 | #define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) | 73 | #define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) |
78 | #define msg_rmid(ns, id) ((struct msg_queue*)ipc_rmid(&msg_ids(ns), id)) | 74 | #define msg_buildid(id, seq) ipc_buildid(id, seq) |
79 | #define msg_checkid(ns, msq, msgid) \ | 75 | |
80 | ipc_checkid(&msg_ids(ns), &msq->q_perm, msgid) | 76 | static void freeque(struct ipc_namespace *, struct msg_queue *); |
81 | #define msg_buildid(ns, id, seq) \ | 77 | static int newque(struct ipc_namespace *, struct ipc_params *); |
82 | ipc_buildid(&msg_ids(ns), id, seq) | ||
83 | |||
84 | static void freeque (struct ipc_namespace *ns, struct msg_queue *msq, int id); | ||
85 | static int newque (struct ipc_namespace *ns, key_t key, int msgflg); | ||
86 | #ifdef CONFIG_PROC_FS | 78 | #ifdef CONFIG_PROC_FS |
87 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it); | 79 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it); |
88 | #endif | 80 | #endif |
@@ -93,7 +85,9 @@ static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) | |||
93 | ns->msg_ctlmax = MSGMAX; | 85 | ns->msg_ctlmax = MSGMAX; |
94 | ns->msg_ctlmnb = MSGMNB; | 86 | ns->msg_ctlmnb = MSGMNB; |
95 | ns->msg_ctlmni = MSGMNI; | 87 | ns->msg_ctlmni = MSGMNI; |
96 | ipc_init_ids(ids, ns->msg_ctlmni); | 88 | atomic_set(&ns->msg_bytes, 0); |
89 | atomic_set(&ns->msg_hdrs, 0); | ||
90 | ipc_init_ids(ids); | ||
97 | } | 91 | } |
98 | 92 | ||
99 | int msg_init_ns(struct ipc_namespace *ns) | 93 | int msg_init_ns(struct ipc_namespace *ns) |
@@ -110,20 +104,25 @@ int msg_init_ns(struct ipc_namespace *ns) | |||
110 | 104 | ||
111 | void msg_exit_ns(struct ipc_namespace *ns) | 105 | void msg_exit_ns(struct ipc_namespace *ns) |
112 | { | 106 | { |
113 | int i; | ||
114 | struct msg_queue *msq; | 107 | struct msg_queue *msq; |
108 | int next_id; | ||
109 | int total, in_use; | ||
110 | |||
111 | down_write(&msg_ids(ns).rw_mutex); | ||
112 | |||
113 | in_use = msg_ids(ns).in_use; | ||
115 | 114 | ||
116 | mutex_lock(&msg_ids(ns).mutex); | 115 | for (total = 0, next_id = 0; total < in_use; next_id++) { |
117 | for (i = 0; i <= msg_ids(ns).max_id; i++) { | 116 | msq = idr_find(&msg_ids(ns).ipcs_idr, next_id); |
118 | msq = msg_lock(ns, i); | ||
119 | if (msq == NULL) | 117 | if (msq == NULL) |
120 | continue; | 118 | continue; |
121 | 119 | ipc_lock_by_ptr(&msq->q_perm); | |
122 | freeque(ns, msq, i); | 120 | freeque(ns, msq); |
121 | total++; | ||
123 | } | 122 | } |
124 | mutex_unlock(&msg_ids(ns).mutex); | ||
125 | 123 | ||
126 | ipc_fini_ids(ns->ids[IPC_MSG_IDS]); | 124 | up_write(&msg_ids(ns).rw_mutex); |
125 | |||
127 | kfree(ns->ids[IPC_MSG_IDS]); | 126 | kfree(ns->ids[IPC_MSG_IDS]); |
128 | ns->ids[IPC_MSG_IDS] = NULL; | 127 | ns->ids[IPC_MSG_IDS] = NULL; |
129 | } | 128 | } |
@@ -136,10 +135,55 @@ void __init msg_init(void) | |||
136 | IPC_MSG_IDS, sysvipc_msg_proc_show); | 135 | IPC_MSG_IDS, sysvipc_msg_proc_show); |
137 | } | 136 | } |
138 | 137 | ||
139 | static int newque (struct ipc_namespace *ns, key_t key, int msgflg) | 138 | /* |
139 | * This routine is called in the paths where the rw_mutex is held to protect | ||
140 | * access to the idr tree. | ||
141 | */ | ||
142 | static inline struct msg_queue *msg_lock_check_down(struct ipc_namespace *ns, | ||
143 | int id) | ||
144 | { | ||
145 | struct kern_ipc_perm *ipcp = ipc_lock_check_down(&msg_ids(ns), id); | ||
146 | |||
147 | return container_of(ipcp, struct msg_queue, q_perm); | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * msg_lock_(check_) routines are called in the paths where the rw_mutex | ||
152 | * is not held. | ||
153 | */ | ||
154 | static inline struct msg_queue *msg_lock(struct ipc_namespace *ns, int id) | ||
155 | { | ||
156 | struct kern_ipc_perm *ipcp = ipc_lock(&msg_ids(ns), id); | ||
157 | |||
158 | return container_of(ipcp, struct msg_queue, q_perm); | ||
159 | } | ||
160 | |||
161 | static inline struct msg_queue *msg_lock_check(struct ipc_namespace *ns, | ||
162 | int id) | ||
163 | { | ||
164 | struct kern_ipc_perm *ipcp = ipc_lock_check(&msg_ids(ns), id); | ||
165 | |||
166 | return container_of(ipcp, struct msg_queue, q_perm); | ||
167 | } | ||
168 | |||
169 | static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s) | ||
170 | { | ||
171 | ipc_rmid(&msg_ids(ns), &s->q_perm); | ||
172 | } | ||
173 | |||
174 | /** | ||
175 | * newque - Create a new msg queue | ||
176 | * @ns: namespace | ||
177 | * @params: ptr to the structure that contains the key and msgflg | ||
178 | * | ||
179 | * Called with msg_ids.rw_mutex held (writer) | ||
180 | */ | ||
181 | static int newque(struct ipc_namespace *ns, struct ipc_params *params) | ||
140 | { | 182 | { |
141 | struct msg_queue *msq; | 183 | struct msg_queue *msq; |
142 | int id, retval; | 184 | int id, retval; |
185 | key_t key = params->key; | ||
186 | int msgflg = params->flg; | ||
143 | 187 | ||
144 | msq = ipc_rcu_alloc(sizeof(*msq)); | 188 | msq = ipc_rcu_alloc(sizeof(*msq)); |
145 | if (!msq) | 189 | if (!msq) |
@@ -155,14 +199,17 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg) | |||
155 | return retval; | 199 | return retval; |
156 | } | 200 | } |
157 | 201 | ||
202 | /* | ||
203 | * ipc_addid() locks msq | ||
204 | */ | ||
158 | id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni); | 205 | id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni); |
159 | if (id == -1) { | 206 | if (id < 0) { |
160 | security_msg_queue_free(msq); | 207 | security_msg_queue_free(msq); |
161 | ipc_rcu_putref(msq); | 208 | ipc_rcu_putref(msq); |
162 | return -ENOSPC; | 209 | return id; |
163 | } | 210 | } |
164 | 211 | ||
165 | msq->q_id = msg_buildid(ns, id, msq->q_perm.seq); | 212 | msq->q_perm.id = msg_buildid(id, msq->q_perm.seq); |
166 | msq->q_stime = msq->q_rtime = 0; | 213 | msq->q_stime = msq->q_rtime = 0; |
167 | msq->q_ctime = get_seconds(); | 214 | msq->q_ctime = get_seconds(); |
168 | msq->q_cbytes = msq->q_qnum = 0; | 215 | msq->q_cbytes = msq->q_qnum = 0; |
@@ -171,9 +218,10 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg) | |||
171 | INIT_LIST_HEAD(&msq->q_messages); | 218 | INIT_LIST_HEAD(&msq->q_messages); |
172 | INIT_LIST_HEAD(&msq->q_receivers); | 219 | INIT_LIST_HEAD(&msq->q_receivers); |
173 | INIT_LIST_HEAD(&msq->q_senders); | 220 | INIT_LIST_HEAD(&msq->q_senders); |
221 | |||
174 | msg_unlock(msq); | 222 | msg_unlock(msq); |
175 | 223 | ||
176 | return msq->q_id; | 224 | return msq->q_perm.id; |
177 | } | 225 | } |
178 | 226 | ||
179 | static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss) | 227 | static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss) |
@@ -224,19 +272,19 @@ static void expunge_all(struct msg_queue *msq, int res) | |||
224 | 272 | ||
225 | /* | 273 | /* |
226 | * freeque() wakes up waiters on the sender and receiver waiting queue, | 274 | * freeque() wakes up waiters on the sender and receiver waiting queue, |
227 | * removes the message queue from message queue ID | 275 | * removes the message queue from message queue ID IDR, and cleans up all the |
228 | * array, and cleans up all the messages associated with this queue. | 276 | * messages associated with this queue. |
229 | * | 277 | * |
230 | * msg_ids.mutex and the spinlock for this message queue is hold | 278 | * msg_ids.rw_mutex (writer) and the spinlock for this message queue are held |
231 | * before freeque() is called. msg_ids.mutex remains locked on exit. | 279 | * before freeque() is called. msg_ids.rw_mutex remains locked on exit. |
232 | */ | 280 | */ |
233 | static void freeque(struct ipc_namespace *ns, struct msg_queue *msq, int id) | 281 | static void freeque(struct ipc_namespace *ns, struct msg_queue *msq) |
234 | { | 282 | { |
235 | struct list_head *tmp; | 283 | struct list_head *tmp; |
236 | 284 | ||
237 | expunge_all(msq, -EIDRM); | 285 | expunge_all(msq, -EIDRM); |
238 | ss_wakeup(&msq->q_senders, 1); | 286 | ss_wakeup(&msq->q_senders, 1); |
239 | msq = msg_rmid(ns, id); | 287 | msg_rmid(ns, msq); |
240 | msg_unlock(msq); | 288 | msg_unlock(msq); |
241 | 289 | ||
242 | tmp = msq->q_messages.next; | 290 | tmp = msq->q_messages.next; |
@@ -244,49 +292,40 @@ static void freeque(struct ipc_namespace *ns, struct msg_queue *msq, int id) | |||
244 | struct msg_msg *msg = list_entry(tmp, struct msg_msg, m_list); | 292 | struct msg_msg *msg = list_entry(tmp, struct msg_msg, m_list); |
245 | 293 | ||
246 | tmp = tmp->next; | 294 | tmp = tmp->next; |
247 | atomic_dec(&msg_hdrs); | 295 | atomic_dec(&ns->msg_hdrs); |
248 | free_msg(msg); | 296 | free_msg(msg); |
249 | } | 297 | } |
250 | atomic_sub(msq->q_cbytes, &msg_bytes); | 298 | atomic_sub(msq->q_cbytes, &ns->msg_bytes); |
251 | security_msg_queue_free(msq); | 299 | security_msg_queue_free(msq); |
252 | ipc_rcu_putref(msq); | 300 | ipc_rcu_putref(msq); |
253 | } | 301 | } |
254 | 302 | ||
303 | /* | ||
304 | * Called with msg_ids.rw_mutex and ipcp locked. | ||
305 | */ | ||
306 | static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg) | ||
307 | { | ||
308 | struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); | ||
309 | |||
310 | return security_msg_queue_associate(msq, msgflg); | ||
311 | } | ||
312 | |||
255 | asmlinkage long sys_msgget(key_t key, int msgflg) | 313 | asmlinkage long sys_msgget(key_t key, int msgflg) |
256 | { | 314 | { |
257 | struct msg_queue *msq; | ||
258 | int id, ret = -EPERM; | ||
259 | struct ipc_namespace *ns; | 315 | struct ipc_namespace *ns; |
316 | struct ipc_ops msg_ops; | ||
317 | struct ipc_params msg_params; | ||
260 | 318 | ||
261 | ns = current->nsproxy->ipc_ns; | 319 | ns = current->nsproxy->ipc_ns; |
262 | |||
263 | mutex_lock(&msg_ids(ns).mutex); | ||
264 | if (key == IPC_PRIVATE) | ||
265 | ret = newque(ns, key, msgflg); | ||
266 | else if ((id = ipc_findkey(&msg_ids(ns), key)) == -1) { /* key not used */ | ||
267 | if (!(msgflg & IPC_CREAT)) | ||
268 | ret = -ENOENT; | ||
269 | else | ||
270 | ret = newque(ns, key, msgflg); | ||
271 | } else if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) { | ||
272 | ret = -EEXIST; | ||
273 | } else { | ||
274 | msq = msg_lock(ns, id); | ||
275 | BUG_ON(msq == NULL); | ||
276 | if (ipcperms(&msq->q_perm, msgflg)) | ||
277 | ret = -EACCES; | ||
278 | else { | ||
279 | int qid = msg_buildid(ns, id, msq->q_perm.seq); | ||
280 | |||
281 | ret = security_msg_queue_associate(msq, msgflg); | ||
282 | if (!ret) | ||
283 | ret = qid; | ||
284 | } | ||
285 | msg_unlock(msq); | ||
286 | } | ||
287 | mutex_unlock(&msg_ids(ns).mutex); | ||
288 | 320 | ||
289 | return ret; | 321 | msg_ops.getnew = newque; |
322 | msg_ops.associate = msg_security; | ||
323 | msg_ops.more_checks = NULL; | ||
324 | |||
325 | msg_params.key = key; | ||
326 | msg_params.flg = msgflg; | ||
327 | |||
328 | return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params); | ||
290 | } | 329 | } |
291 | 330 | ||
292 | static inline unsigned long | 331 | static inline unsigned long |
@@ -420,23 +459,23 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) | |||
420 | msginfo.msgmnb = ns->msg_ctlmnb; | 459 | msginfo.msgmnb = ns->msg_ctlmnb; |
421 | msginfo.msgssz = MSGSSZ; | 460 | msginfo.msgssz = MSGSSZ; |
422 | msginfo.msgseg = MSGSEG; | 461 | msginfo.msgseg = MSGSEG; |
423 | mutex_lock(&msg_ids(ns).mutex); | 462 | down_read(&msg_ids(ns).rw_mutex); |
424 | if (cmd == MSG_INFO) { | 463 | if (cmd == MSG_INFO) { |
425 | msginfo.msgpool = msg_ids(ns).in_use; | 464 | msginfo.msgpool = msg_ids(ns).in_use; |
426 | msginfo.msgmap = atomic_read(&msg_hdrs); | 465 | msginfo.msgmap = atomic_read(&ns->msg_hdrs); |
427 | msginfo.msgtql = atomic_read(&msg_bytes); | 466 | msginfo.msgtql = atomic_read(&ns->msg_bytes); |
428 | } else { | 467 | } else { |
429 | msginfo.msgmap = MSGMAP; | 468 | msginfo.msgmap = MSGMAP; |
430 | msginfo.msgpool = MSGPOOL; | 469 | msginfo.msgpool = MSGPOOL; |
431 | msginfo.msgtql = MSGTQL; | 470 | msginfo.msgtql = MSGTQL; |
432 | } | 471 | } |
433 | max_id = msg_ids(ns).max_id; | 472 | max_id = ipc_get_maxid(&msg_ids(ns)); |
434 | mutex_unlock(&msg_ids(ns).mutex); | 473 | up_read(&msg_ids(ns).rw_mutex); |
435 | if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) | 474 | if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) |
436 | return -EFAULT; | 475 | return -EFAULT; |
437 | return (max_id < 0) ? 0 : max_id; | 476 | return (max_id < 0) ? 0 : max_id; |
438 | } | 477 | } |
439 | case MSG_STAT: | 478 | case MSG_STAT: /* msqid is an index rather than a msg queue id */ |
440 | case IPC_STAT: | 479 | case IPC_STAT: |
441 | { | 480 | { |
442 | struct msqid64_ds tbuf; | 481 | struct msqid64_ds tbuf; |
@@ -444,21 +483,16 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) | |||
444 | 483 | ||
445 | if (!buf) | 484 | if (!buf) |
446 | return -EFAULT; | 485 | return -EFAULT; |
447 | if (cmd == MSG_STAT && msqid >= msg_ids(ns).entries->size) | ||
448 | return -EINVAL; | ||
449 | |||
450 | memset(&tbuf, 0, sizeof(tbuf)); | ||
451 | |||
452 | msq = msg_lock(ns, msqid); | ||
453 | if (msq == NULL) | ||
454 | return -EINVAL; | ||
455 | 486 | ||
456 | if (cmd == MSG_STAT) { | 487 | if (cmd == MSG_STAT) { |
457 | success_return = msg_buildid(ns, msqid, msq->q_perm.seq); | 488 | msq = msg_lock(ns, msqid); |
489 | if (IS_ERR(msq)) | ||
490 | return PTR_ERR(msq); | ||
491 | success_return = msq->q_perm.id; | ||
458 | } else { | 492 | } else { |
459 | err = -EIDRM; | 493 | msq = msg_lock_check(ns, msqid); |
460 | if (msg_checkid(ns, msq, msqid)) | 494 | if (IS_ERR(msq)) |
461 | goto out_unlock; | 495 | return PTR_ERR(msq); |
462 | success_return = 0; | 496 | success_return = 0; |
463 | } | 497 | } |
464 | err = -EACCES; | 498 | err = -EACCES; |
@@ -469,6 +503,8 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) | |||
469 | if (err) | 503 | if (err) |
470 | goto out_unlock; | 504 | goto out_unlock; |
471 | 505 | ||
506 | memset(&tbuf, 0, sizeof(tbuf)); | ||
507 | |||
472 | kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm); | 508 | kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm); |
473 | tbuf.msg_stime = msq->q_stime; | 509 | tbuf.msg_stime = msq->q_stime; |
474 | tbuf.msg_rtime = msq->q_rtime; | 510 | tbuf.msg_rtime = msq->q_rtime; |
@@ -495,15 +531,13 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) | |||
495 | return -EINVAL; | 531 | return -EINVAL; |
496 | } | 532 | } |
497 | 533 | ||
498 | mutex_lock(&msg_ids(ns).mutex); | 534 | down_write(&msg_ids(ns).rw_mutex); |
499 | msq = msg_lock(ns, msqid); | 535 | msq = msg_lock_check_down(ns, msqid); |
500 | err = -EINVAL; | 536 | if (IS_ERR(msq)) { |
501 | if (msq == NULL) | 537 | err = PTR_ERR(msq); |
502 | goto out_up; | 538 | goto out_up; |
539 | } | ||
503 | 540 | ||
504 | err = -EIDRM; | ||
505 | if (msg_checkid(ns, msq, msqid)) | ||
506 | goto out_unlock_up; | ||
507 | ipcp = &msq->q_perm; | 541 | ipcp = &msq->q_perm; |
508 | 542 | ||
509 | err = audit_ipc_obj(ipcp); | 543 | err = audit_ipc_obj(ipcp); |
@@ -552,12 +586,12 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) | |||
552 | break; | 586 | break; |
553 | } | 587 | } |
554 | case IPC_RMID: | 588 | case IPC_RMID: |
555 | freeque(ns, msq, msqid); | 589 | freeque(ns, msq); |
556 | break; | 590 | break; |
557 | } | 591 | } |
558 | err = 0; | 592 | err = 0; |
559 | out_up: | 593 | out_up: |
560 | mutex_unlock(&msg_ids(ns).mutex); | 594 | up_write(&msg_ids(ns).rw_mutex); |
561 | return err; | 595 | return err; |
562 | out_unlock_up: | 596 | out_unlock_up: |
563 | msg_unlock(msq); | 597 | msg_unlock(msq); |
@@ -611,7 +645,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg) | |||
611 | msr->r_msg = ERR_PTR(-E2BIG); | 645 | msr->r_msg = ERR_PTR(-E2BIG); |
612 | } else { | 646 | } else { |
613 | msr->r_msg = NULL; | 647 | msr->r_msg = NULL; |
614 | msq->q_lrpid = msr->r_tsk->pid; | 648 | msq->q_lrpid = task_pid_vnr(msr->r_tsk); |
615 | msq->q_rtime = get_seconds(); | 649 | msq->q_rtime = get_seconds(); |
616 | wake_up_process(msr->r_tsk); | 650 | wake_up_process(msr->r_tsk); |
617 | smp_mb(); | 651 | smp_mb(); |
@@ -646,14 +680,11 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext, | |||
646 | msg->m_type = mtype; | 680 | msg->m_type = mtype; |
647 | msg->m_ts = msgsz; | 681 | msg->m_ts = msgsz; |
648 | 682 | ||
649 | msq = msg_lock(ns, msqid); | 683 | msq = msg_lock_check(ns, msqid); |
650 | err = -EINVAL; | 684 | if (IS_ERR(msq)) { |
651 | if (msq == NULL) | 685 | err = PTR_ERR(msq); |
652 | goto out_free; | 686 | goto out_free; |
653 | 687 | } | |
654 | err= -EIDRM; | ||
655 | if (msg_checkid(ns, msq, msqid)) | ||
656 | goto out_unlock_free; | ||
657 | 688 | ||
658 | for (;;) { | 689 | for (;;) { |
659 | struct msg_sender s; | 690 | struct msg_sender s; |
@@ -695,7 +726,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext, | |||
695 | } | 726 | } |
696 | } | 727 | } |
697 | 728 | ||
698 | msq->q_lspid = current->tgid; | 729 | msq->q_lspid = task_tgid_vnr(current); |
699 | msq->q_stime = get_seconds(); | 730 | msq->q_stime = get_seconds(); |
700 | 731 | ||
701 | if (!pipelined_send(msq, msg)) { | 732 | if (!pipelined_send(msq, msg)) { |
@@ -703,8 +734,8 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext, | |||
703 | list_add_tail(&msg->m_list, &msq->q_messages); | 734 | list_add_tail(&msg->m_list, &msq->q_messages); |
704 | msq->q_cbytes += msgsz; | 735 | msq->q_cbytes += msgsz; |
705 | msq->q_qnum++; | 736 | msq->q_qnum++; |
706 | atomic_add(msgsz, &msg_bytes); | 737 | atomic_add(msgsz, &ns->msg_bytes); |
707 | atomic_inc(&msg_hdrs); | 738 | atomic_inc(&ns->msg_hdrs); |
708 | } | 739 | } |
709 | 740 | ||
710 | err = 0; | 741 | err = 0; |
@@ -760,13 +791,9 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | |||
760 | mode = convert_mode(&msgtyp, msgflg); | 791 | mode = convert_mode(&msgtyp, msgflg); |
761 | ns = current->nsproxy->ipc_ns; | 792 | ns = current->nsproxy->ipc_ns; |
762 | 793 | ||
763 | msq = msg_lock(ns, msqid); | 794 | msq = msg_lock_check(ns, msqid); |
764 | if (msq == NULL) | 795 | if (IS_ERR(msq)) |
765 | return -EINVAL; | 796 | return PTR_ERR(msq); |
766 | |||
767 | msg = ERR_PTR(-EIDRM); | ||
768 | if (msg_checkid(ns, msq, msqid)) | ||
769 | goto out_unlock; | ||
770 | 797 | ||
771 | for (;;) { | 798 | for (;;) { |
772 | struct msg_receiver msr_d; | 799 | struct msg_receiver msr_d; |
@@ -810,10 +837,10 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | |||
810 | list_del(&msg->m_list); | 837 | list_del(&msg->m_list); |
811 | msq->q_qnum--; | 838 | msq->q_qnum--; |
812 | msq->q_rtime = get_seconds(); | 839 | msq->q_rtime = get_seconds(); |
813 | msq->q_lrpid = current->tgid; | 840 | msq->q_lrpid = task_tgid_vnr(current); |
814 | msq->q_cbytes -= msg->m_ts; | 841 | msq->q_cbytes -= msg->m_ts; |
815 | atomic_sub(msg->m_ts, &msg_bytes); | 842 | atomic_sub(msg->m_ts, &ns->msg_bytes); |
816 | atomic_dec(&msg_hdrs); | 843 | atomic_dec(&ns->msg_hdrs); |
817 | ss_wakeup(&msq->q_senders, 0); | 844 | ss_wakeup(&msq->q_senders, 0); |
818 | msg_unlock(msq); | 845 | msg_unlock(msq); |
819 | break; | 846 | break; |
@@ -926,7 +953,7 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it) | |||
926 | return seq_printf(s, | 953 | return seq_printf(s, |
927 | "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", | 954 | "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", |
928 | msq->q_perm.key, | 955 | msq->q_perm.key, |
929 | msq->q_id, | 956 | msq->q_perm.id, |
930 | msq->q_perm.mode, | 957 | msq->q_perm.mode, |
931 | msq->q_cbytes, | 958 | msq->q_cbytes, |
932 | msq->q_qnum, | 959 | msq->q_qnum, |