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, |
