diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/Makefile | 1 | ||||
-rw-r--r-- | ipc/ipc_sysctl.c | 1 | ||||
-rw-r--r-- | ipc/mqueue.c | 5 | ||||
-rw-r--r-- | ipc/msg.c | 57 | ||||
-rw-r--r-- | ipc/namespace.c | 86 | ||||
-rw-r--r-- | ipc/sem.c | 94 | ||||
-rw-r--r-- | ipc/shm.c | 56 | ||||
-rw-r--r-- | ipc/util.c | 122 | ||||
-rw-r--r-- | ipc/util.h | 78 |
9 files changed, 210 insertions, 290 deletions
diff --git a/ipc/Makefile b/ipc/Makefile index b93bba6652f1..5fc5e33ea047 100644 --- a/ipc/Makefile +++ b/ipc/Makefile | |||
@@ -7,4 +7,5 @@ obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o | |||
7 | obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o | 7 | obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o |
8 | obj_mq-$(CONFIG_COMPAT) += compat_mq.o | 8 | obj_mq-$(CONFIG_COMPAT) += compat_mq.o |
9 | obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) | 9 | obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) |
10 | obj-$(CONFIG_IPC_NS) += namespace.o | ||
10 | 11 | ||
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 79e24e878c1e..7f4235bed51b 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/nsproxy.h> | 14 | #include <linux/nsproxy.h> |
15 | #include <linux/sysctl.h> | 15 | #include <linux/sysctl.h> |
16 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
17 | #include <linux/ipc_namespace.h> | ||
17 | 18 | ||
18 | static void *get_ipc(ctl_table *table) | 19 | static void *get_ipc(ctl_table *table) |
19 | { | 20 | { |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 6ca7b97114f3..60f7a27f7a9e 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -332,8 +332,7 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data, | |||
332 | (info->notify_owner && | 332 | (info->notify_owner && |
333 | info->notify.sigev_notify == SIGEV_SIGNAL) ? | 333 | info->notify.sigev_notify == SIGEV_SIGNAL) ? |
334 | info->notify.sigev_signo : 0, | 334 | info->notify.sigev_signo : 0, |
335 | pid_nr_ns(info->notify_owner, | 335 | pid_vnr(info->notify_owner)); |
336 | current->nsproxy->pid_ns)); | ||
337 | spin_unlock(&info->lock); | 336 | spin_unlock(&info->lock); |
338 | buffer[sizeof(buffer)-1] = '\0'; | 337 | buffer[sizeof(buffer)-1] = '\0'; |
339 | slen = strlen(buffer)+1; | 338 | slen = strlen(buffer)+1; |
@@ -510,7 +509,7 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
510 | sig_i.si_errno = 0; | 509 | sig_i.si_errno = 0; |
511 | sig_i.si_code = SI_MESGQ; | 510 | sig_i.si_code = SI_MESGQ; |
512 | sig_i.si_value = info->notify.sigev_value; | 511 | sig_i.si_value = info->notify.sigev_value; |
513 | sig_i.si_pid = task_pid_vnr(current); | 512 | sig_i.si_pid = task_tgid_vnr(current); |
514 | sig_i.si_uid = current->uid; | 513 | sig_i.si_uid = current->uid; |
515 | 514 | ||
516 | kill_pid_info(info->notify.sigev_signo, | 515 | kill_pid_info(info->notify.sigev_signo, |
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
37 | #include <linux/rwsem.h> | 37 | #include <linux/rwsem.h> |
38 | #include <linux/nsproxy.h> | 38 | #include <linux/nsproxy.h> |
39 | #include <linux/ipc_namespace.h> | ||
39 | 40 | ||
40 | #include <asm/current.h> | 41 | #include <asm/current.h> |
41 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
@@ -66,72 +67,37 @@ struct msg_sender { | |||
66 | #define SEARCH_NOTEQUAL 3 | 67 | #define SEARCH_NOTEQUAL 3 |
67 | #define SEARCH_LESSEQUAL 4 | 68 | #define SEARCH_LESSEQUAL 4 |
68 | 69 | ||
69 | static struct ipc_ids init_msg_ids; | 70 | #define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS]) |
70 | |||
71 | #define msg_ids(ns) (*((ns)->ids[IPC_MSG_IDS])) | ||
72 | 71 | ||
73 | #define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) | 72 | #define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) |
74 | #define msg_buildid(id, seq) ipc_buildid(id, seq) | 73 | #define msg_buildid(id, seq) ipc_buildid(id, seq) |
75 | 74 | ||
76 | static void freeque(struct ipc_namespace *, struct msg_queue *); | 75 | static void freeque(struct ipc_namespace *, struct kern_ipc_perm *); |
77 | static int newque(struct ipc_namespace *, struct ipc_params *); | 76 | static int newque(struct ipc_namespace *, struct ipc_params *); |
78 | #ifdef CONFIG_PROC_FS | 77 | #ifdef CONFIG_PROC_FS |
79 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it); | 78 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it); |
80 | #endif | 79 | #endif |
81 | 80 | ||
82 | static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) | 81 | void msg_init_ns(struct ipc_namespace *ns) |
83 | { | 82 | { |
84 | ns->ids[IPC_MSG_IDS] = ids; | ||
85 | ns->msg_ctlmax = MSGMAX; | 83 | ns->msg_ctlmax = MSGMAX; |
86 | ns->msg_ctlmnb = MSGMNB; | 84 | ns->msg_ctlmnb = MSGMNB; |
87 | ns->msg_ctlmni = MSGMNI; | 85 | ns->msg_ctlmni = MSGMNI; |
88 | atomic_set(&ns->msg_bytes, 0); | 86 | atomic_set(&ns->msg_bytes, 0); |
89 | atomic_set(&ns->msg_hdrs, 0); | 87 | atomic_set(&ns->msg_hdrs, 0); |
90 | ipc_init_ids(ids); | 88 | ipc_init_ids(&ns->ids[IPC_MSG_IDS]); |
91 | } | ||
92 | |||
93 | int msg_init_ns(struct ipc_namespace *ns) | ||
94 | { | ||
95 | struct ipc_ids *ids; | ||
96 | |||
97 | ids = kmalloc(sizeof(struct ipc_ids), GFP_KERNEL); | ||
98 | if (ids == NULL) | ||
99 | return -ENOMEM; | ||
100 | |||
101 | __msg_init_ns(ns, ids); | ||
102 | return 0; | ||
103 | } | 89 | } |
104 | 90 | ||
91 | #ifdef CONFIG_IPC_NS | ||
105 | void msg_exit_ns(struct ipc_namespace *ns) | 92 | void msg_exit_ns(struct ipc_namespace *ns) |
106 | { | 93 | { |
107 | struct msg_queue *msq; | 94 | free_ipcs(ns, &msg_ids(ns), freeque); |
108 | struct kern_ipc_perm *perm; | ||
109 | int next_id; | ||
110 | int total, in_use; | ||
111 | |||
112 | down_write(&msg_ids(ns).rw_mutex); | ||
113 | |||
114 | in_use = msg_ids(ns).in_use; | ||
115 | |||
116 | for (total = 0, next_id = 0; total < in_use; next_id++) { | ||
117 | perm = idr_find(&msg_ids(ns).ipcs_idr, next_id); | ||
118 | if (perm == NULL) | ||
119 | continue; | ||
120 | ipc_lock_by_ptr(perm); | ||
121 | msq = container_of(perm, struct msg_queue, q_perm); | ||
122 | freeque(ns, msq); | ||
123 | total++; | ||
124 | } | ||
125 | |||
126 | up_write(&msg_ids(ns).rw_mutex); | ||
127 | |||
128 | kfree(ns->ids[IPC_MSG_IDS]); | ||
129 | ns->ids[IPC_MSG_IDS] = NULL; | ||
130 | } | 95 | } |
96 | #endif | ||
131 | 97 | ||
132 | void __init msg_init(void) | 98 | void __init msg_init(void) |
133 | { | 99 | { |
134 | __msg_init_ns(&init_ipc_ns, &init_msg_ids); | 100 | msg_init_ns(&init_ipc_ns); |
135 | ipc_init_proc_interface("sysvipc/msg", | 101 | ipc_init_proc_interface("sysvipc/msg", |
136 | " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", | 102 | " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", |
137 | IPC_MSG_IDS, sysvipc_msg_proc_show); | 103 | IPC_MSG_IDS, sysvipc_msg_proc_show); |
@@ -289,9 +255,10 @@ static void expunge_all(struct msg_queue *msq, int res) | |||
289 | * msg_ids.rw_mutex (writer) and the spinlock for this message queue are held | 255 | * msg_ids.rw_mutex (writer) and the spinlock for this message queue are held |
290 | * before freeque() is called. msg_ids.rw_mutex remains locked on exit. | 256 | * before freeque() is called. msg_ids.rw_mutex remains locked on exit. |
291 | */ | 257 | */ |
292 | static void freeque(struct ipc_namespace *ns, struct msg_queue *msq) | 258 | static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) |
293 | { | 259 | { |
294 | struct list_head *tmp; | 260 | struct list_head *tmp; |
261 | struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); | ||
295 | 262 | ||
296 | expunge_all(msq, -EIDRM); | 263 | expunge_all(msq, -EIDRM); |
297 | ss_wakeup(&msq->q_senders, 1); | 264 | ss_wakeup(&msq->q_senders, 1); |
@@ -597,7 +564,7 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) | |||
597 | break; | 564 | break; |
598 | } | 565 | } |
599 | case IPC_RMID: | 566 | case IPC_RMID: |
600 | freeque(ns, msq); | 567 | freeque(ns, &msq->q_perm); |
601 | break; | 568 | break; |
602 | } | 569 | } |
603 | err = 0; | 570 | err = 0; |
diff --git a/ipc/namespace.c b/ipc/namespace.c new file mode 100644 index 000000000000..1b967655eb35 --- /dev/null +++ b/ipc/namespace.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * linux/ipc/namespace.c | ||
3 | * Copyright (C) 2006 Pavel Emelyanov <xemul@openvz.org> OpenVZ, SWsoft Inc. | ||
4 | */ | ||
5 | |||
6 | #include <linux/ipc.h> | ||
7 | #include <linux/msg.h> | ||
8 | #include <linux/ipc_namespace.h> | ||
9 | #include <linux/rcupdate.h> | ||
10 | #include <linux/nsproxy.h> | ||
11 | #include <linux/slab.h> | ||
12 | |||
13 | #include "util.h" | ||
14 | |||
15 | static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) | ||
16 | { | ||
17 | struct ipc_namespace *ns; | ||
18 | |||
19 | ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL); | ||
20 | if (ns == NULL) | ||
21 | return ERR_PTR(-ENOMEM); | ||
22 | |||
23 | sem_init_ns(ns); | ||
24 | msg_init_ns(ns); | ||
25 | shm_init_ns(ns); | ||
26 | |||
27 | kref_init(&ns->kref); | ||
28 | return ns; | ||
29 | } | ||
30 | |||
31 | struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) | ||
32 | { | ||
33 | struct ipc_namespace *new_ns; | ||
34 | |||
35 | BUG_ON(!ns); | ||
36 | get_ipc_ns(ns); | ||
37 | |||
38 | if (!(flags & CLONE_NEWIPC)) | ||
39 | return ns; | ||
40 | |||
41 | new_ns = clone_ipc_ns(ns); | ||
42 | |||
43 | put_ipc_ns(ns); | ||
44 | return new_ns; | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * free_ipcs - free all ipcs of one type | ||
49 | * @ns: the namespace to remove the ipcs from | ||
50 | * @ids: the table of ipcs to free | ||
51 | * @free: the function called to free each individual ipc | ||
52 | * | ||
53 | * Called for each kind of ipc when an ipc_namespace exits. | ||
54 | */ | ||
55 | void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
56 | void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)) | ||
57 | { | ||
58 | struct kern_ipc_perm *perm; | ||
59 | int next_id; | ||
60 | int total, in_use; | ||
61 | |||
62 | down_write(&ids->rw_mutex); | ||
63 | |||
64 | in_use = ids->in_use; | ||
65 | |||
66 | for (total = 0, next_id = 0; total < in_use; next_id++) { | ||
67 | perm = idr_find(&ids->ipcs_idr, next_id); | ||
68 | if (perm == NULL) | ||
69 | continue; | ||
70 | ipc_lock_by_ptr(perm); | ||
71 | free(ns, perm); | ||
72 | total++; | ||
73 | } | ||
74 | up_write(&ids->rw_mutex); | ||
75 | } | ||
76 | |||
77 | void free_ipc_ns(struct kref *kref) | ||
78 | { | ||
79 | struct ipc_namespace *ns; | ||
80 | |||
81 | ns = container_of(kref, struct ipc_namespace, kref); | ||
82 | sem_exit_ns(ns); | ||
83 | msg_exit_ns(ns); | ||
84 | shm_exit_ns(ns); | ||
85 | kfree(ns); | ||
86 | } | ||
@@ -82,20 +82,19 @@ | |||
82 | #include <linux/seq_file.h> | 82 | #include <linux/seq_file.h> |
83 | #include <linux/rwsem.h> | 83 | #include <linux/rwsem.h> |
84 | #include <linux/nsproxy.h> | 84 | #include <linux/nsproxy.h> |
85 | #include <linux/ipc_namespace.h> | ||
85 | 86 | ||
86 | #include <asm/uaccess.h> | 87 | #include <asm/uaccess.h> |
87 | #include "util.h" | 88 | #include "util.h" |
88 | 89 | ||
89 | #define sem_ids(ns) (*((ns)->ids[IPC_SEM_IDS])) | 90 | #define sem_ids(ns) ((ns)->ids[IPC_SEM_IDS]) |
90 | 91 | ||
91 | #define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm) | 92 | #define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm) |
92 | #define sem_checkid(sma, semid) ipc_checkid(&sma->sem_perm, semid) | 93 | #define sem_checkid(sma, semid) ipc_checkid(&sma->sem_perm, semid) |
93 | #define sem_buildid(id, seq) ipc_buildid(id, seq) | 94 | #define sem_buildid(id, seq) ipc_buildid(id, seq) |
94 | 95 | ||
95 | static struct ipc_ids init_sem_ids; | ||
96 | |||
97 | static int newary(struct ipc_namespace *, struct ipc_params *); | 96 | static int newary(struct ipc_namespace *, struct ipc_params *); |
98 | static void freeary(struct ipc_namespace *, struct sem_array *); | 97 | static void freeary(struct ipc_namespace *, struct kern_ipc_perm *); |
99 | #ifdef CONFIG_PROC_FS | 98 | #ifdef CONFIG_PROC_FS |
100 | static int sysvipc_sem_proc_show(struct seq_file *s, void *it); | 99 | static int sysvipc_sem_proc_show(struct seq_file *s, void *it); |
101 | #endif | 100 | #endif |
@@ -117,58 +116,26 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it); | |||
117 | #define sc_semopm sem_ctls[2] | 116 | #define sc_semopm sem_ctls[2] |
118 | #define sc_semmni sem_ctls[3] | 117 | #define sc_semmni sem_ctls[3] |
119 | 118 | ||
120 | static void __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) | 119 | void sem_init_ns(struct ipc_namespace *ns) |
121 | { | 120 | { |
122 | ns->ids[IPC_SEM_IDS] = ids; | ||
123 | ns->sc_semmsl = SEMMSL; | 121 | ns->sc_semmsl = SEMMSL; |
124 | ns->sc_semmns = SEMMNS; | 122 | ns->sc_semmns = SEMMNS; |
125 | ns->sc_semopm = SEMOPM; | 123 | ns->sc_semopm = SEMOPM; |
126 | ns->sc_semmni = SEMMNI; | 124 | ns->sc_semmni = SEMMNI; |
127 | ns->used_sems = 0; | 125 | ns->used_sems = 0; |
128 | ipc_init_ids(ids); | 126 | ipc_init_ids(&ns->ids[IPC_SEM_IDS]); |
129 | } | ||
130 | |||
131 | int sem_init_ns(struct ipc_namespace *ns) | ||
132 | { | ||
133 | struct ipc_ids *ids; | ||
134 | |||
135 | ids = kmalloc(sizeof(struct ipc_ids), GFP_KERNEL); | ||
136 | if (ids == NULL) | ||
137 | return -ENOMEM; | ||
138 | |||
139 | __sem_init_ns(ns, ids); | ||
140 | return 0; | ||
141 | } | 127 | } |
142 | 128 | ||
129 | #ifdef CONFIG_IPC_NS | ||
143 | void sem_exit_ns(struct ipc_namespace *ns) | 130 | void sem_exit_ns(struct ipc_namespace *ns) |
144 | { | 131 | { |
145 | struct sem_array *sma; | 132 | free_ipcs(ns, &sem_ids(ns), freeary); |
146 | struct kern_ipc_perm *perm; | ||
147 | int next_id; | ||
148 | int total, in_use; | ||
149 | |||
150 | down_write(&sem_ids(ns).rw_mutex); | ||
151 | |||
152 | in_use = sem_ids(ns).in_use; | ||
153 | |||
154 | for (total = 0, next_id = 0; total < in_use; next_id++) { | ||
155 | perm = idr_find(&sem_ids(ns).ipcs_idr, next_id); | ||
156 | if (perm == NULL) | ||
157 | continue; | ||
158 | ipc_lock_by_ptr(perm); | ||
159 | sma = container_of(perm, struct sem_array, sem_perm); | ||
160 | freeary(ns, sma); | ||
161 | total++; | ||
162 | } | ||
163 | up_write(&sem_ids(ns).rw_mutex); | ||
164 | |||
165 | kfree(ns->ids[IPC_SEM_IDS]); | ||
166 | ns->ids[IPC_SEM_IDS] = NULL; | ||
167 | } | 133 | } |
134 | #endif | ||
168 | 135 | ||
169 | void __init sem_init (void) | 136 | void __init sem_init (void) |
170 | { | 137 | { |
171 | __sem_init_ns(&init_ipc_ns, &init_sem_ids); | 138 | sem_init_ns(&init_ipc_ns); |
172 | ipc_init_proc_interface("sysvipc/sem", | 139 | ipc_init_proc_interface("sysvipc/sem", |
173 | " key semid perms nsems uid gid cuid cgid otime ctime\n", | 140 | " key semid perms nsems uid gid cuid cgid otime ctime\n", |
174 | IPC_SEM_IDS, sysvipc_sem_proc_show); | 141 | IPC_SEM_IDS, sysvipc_sem_proc_show); |
@@ -557,10 +524,11 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum) | |||
557 | * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex | 524 | * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex |
558 | * remains locked on exit. | 525 | * remains locked on exit. |
559 | */ | 526 | */ |
560 | static void freeary(struct ipc_namespace *ns, struct sem_array *sma) | 527 | static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) |
561 | { | 528 | { |
562 | struct sem_undo *un; | 529 | struct sem_undo *un; |
563 | struct sem_queue *q; | 530 | struct sem_queue *q; |
531 | struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm); | ||
564 | 532 | ||
565 | /* Invalidate the existing undo structures for this semaphore set. | 533 | /* Invalidate the existing undo structures for this semaphore set. |
566 | * (They will be freed without any further action in exit_sem() | 534 | * (They will be freed without any further action in exit_sem() |
@@ -614,8 +582,8 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, | |||
614 | } | 582 | } |
615 | } | 583 | } |
616 | 584 | ||
617 | static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum, | 585 | static int semctl_nolock(struct ipc_namespace *ns, int semid, |
618 | int cmd, int version, union semun arg) | 586 | int cmd, int version, union semun arg) |
619 | { | 587 | { |
620 | int err = -EINVAL; | 588 | int err = -EINVAL; |
621 | struct sem_array *sma; | 589 | struct sem_array *sma; |
@@ -654,14 +622,23 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum, | |||
654 | return -EFAULT; | 622 | return -EFAULT; |
655 | return (max_id < 0) ? 0: max_id; | 623 | return (max_id < 0) ? 0: max_id; |
656 | } | 624 | } |
625 | case IPC_STAT: | ||
657 | case SEM_STAT: | 626 | case SEM_STAT: |
658 | { | 627 | { |
659 | struct semid64_ds tbuf; | 628 | struct semid64_ds tbuf; |
660 | int id; | 629 | int id; |
661 | 630 | ||
662 | sma = sem_lock(ns, semid); | 631 | if (cmd == SEM_STAT) { |
663 | if (IS_ERR(sma)) | 632 | sma = sem_lock(ns, semid); |
664 | return PTR_ERR(sma); | 633 | if (IS_ERR(sma)) |
634 | return PTR_ERR(sma); | ||
635 | id = sma->sem_perm.id; | ||
636 | } else { | ||
637 | sma = sem_lock_check(ns, semid); | ||
638 | if (IS_ERR(sma)) | ||
639 | return PTR_ERR(sma); | ||
640 | id = 0; | ||
641 | } | ||
665 | 642 | ||
666 | err = -EACCES; | 643 | err = -EACCES; |
667 | if (ipcperms (&sma->sem_perm, S_IRUGO)) | 644 | if (ipcperms (&sma->sem_perm, S_IRUGO)) |
@@ -671,8 +648,6 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum, | |||
671 | if (err) | 648 | if (err) |
672 | goto out_unlock; | 649 | goto out_unlock; |
673 | 650 | ||
674 | id = sma->sem_perm.id; | ||
675 | |||
676 | memset(&tbuf, 0, sizeof(tbuf)); | 651 | memset(&tbuf, 0, sizeof(tbuf)); |
677 | 652 | ||
678 | kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm); | 653 | kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm); |
@@ -807,19 +782,6 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
807 | err = 0; | 782 | err = 0; |
808 | goto out_unlock; | 783 | goto out_unlock; |
809 | } | 784 | } |
810 | case IPC_STAT: | ||
811 | { | ||
812 | struct semid64_ds tbuf; | ||
813 | memset(&tbuf,0,sizeof(tbuf)); | ||
814 | kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm); | ||
815 | tbuf.sem_otime = sma->sem_otime; | ||
816 | tbuf.sem_ctime = sma->sem_ctime; | ||
817 | tbuf.sem_nsems = sma->sem_nsems; | ||
818 | sem_unlock(sma); | ||
819 | if (copy_semid_to_user (arg.buf, &tbuf, version)) | ||
820 | return -EFAULT; | ||
821 | return 0; | ||
822 | } | ||
823 | /* GETVAL, GETPID, GETNCTN, GETZCNT, SETVAL: fall-through */ | 785 | /* GETVAL, GETPID, GETNCTN, GETZCNT, SETVAL: fall-through */ |
824 | } | 786 | } |
825 | err = -EINVAL; | 787 | err = -EINVAL; |
@@ -947,7 +909,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, | |||
947 | 909 | ||
948 | switch(cmd){ | 910 | switch(cmd){ |
949 | case IPC_RMID: | 911 | case IPC_RMID: |
950 | freeary(ns, sma); | 912 | freeary(ns, ipcp); |
951 | err = 0; | 913 | err = 0; |
952 | break; | 914 | break; |
953 | case IPC_SET: | 915 | case IPC_SET: |
@@ -986,15 +948,15 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) | |||
986 | switch(cmd) { | 948 | switch(cmd) { |
987 | case IPC_INFO: | 949 | case IPC_INFO: |
988 | case SEM_INFO: | 950 | case SEM_INFO: |
951 | case IPC_STAT: | ||
989 | case SEM_STAT: | 952 | case SEM_STAT: |
990 | err = semctl_nolock(ns,semid,semnum,cmd,version,arg); | 953 | err = semctl_nolock(ns, semid, cmd, version, arg); |
991 | return err; | 954 | return err; |
992 | case GETALL: | 955 | case GETALL: |
993 | case GETVAL: | 956 | case GETVAL: |
994 | case GETPID: | 957 | case GETPID: |
995 | case GETNCNT: | 958 | case GETNCNT: |
996 | case GETZCNT: | 959 | case GETZCNT: |
997 | case IPC_STAT: | ||
998 | case SETVAL: | 960 | case SETVAL: |
999 | case SETALL: | 961 | case SETALL: |
1000 | err = semctl_main(ns,semid,semnum,cmd,version,arg); | 962 | err = semctl_main(ns,semid,semnum,cmd,version,arg); |
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/rwsem.h> | 38 | #include <linux/rwsem.h> |
39 | #include <linux/nsproxy.h> | 39 | #include <linux/nsproxy.h> |
40 | #include <linux/mount.h> | 40 | #include <linux/mount.h> |
41 | #include <linux/ipc_namespace.h> | ||
41 | 42 | ||
42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
43 | 44 | ||
@@ -55,9 +56,7 @@ struct shm_file_data { | |||
55 | static const struct file_operations shm_file_operations; | 56 | static const struct file_operations shm_file_operations; |
56 | static struct vm_operations_struct shm_vm_ops; | 57 | static struct vm_operations_struct shm_vm_ops; |
57 | 58 | ||
58 | static struct ipc_ids init_shm_ids; | 59 | #define shm_ids(ns) ((ns)->ids[IPC_SHM_IDS]) |
59 | |||
60 | #define shm_ids(ns) (*((ns)->ids[IPC_SHM_IDS])) | ||
61 | 60 | ||
62 | #define shm_unlock(shp) \ | 61 | #define shm_unlock(shp) \ |
63 | ipc_unlock(&(shp)->shm_perm) | 62 | ipc_unlock(&(shp)->shm_perm) |
@@ -71,22 +70,24 @@ static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp); | |||
71 | static int sysvipc_shm_proc_show(struct seq_file *s, void *it); | 70 | static int sysvipc_shm_proc_show(struct seq_file *s, void *it); |
72 | #endif | 71 | #endif |
73 | 72 | ||
74 | static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) | 73 | void shm_init_ns(struct ipc_namespace *ns) |
75 | { | 74 | { |
76 | ns->ids[IPC_SHM_IDS] = ids; | ||
77 | ns->shm_ctlmax = SHMMAX; | 75 | ns->shm_ctlmax = SHMMAX; |
78 | ns->shm_ctlall = SHMALL; | 76 | ns->shm_ctlall = SHMALL; |
79 | ns->shm_ctlmni = SHMMNI; | 77 | ns->shm_ctlmni = SHMMNI; |
80 | ns->shm_tot = 0; | 78 | ns->shm_tot = 0; |
81 | ipc_init_ids(ids); | 79 | ipc_init_ids(&ns->ids[IPC_SHM_IDS]); |
82 | } | 80 | } |
83 | 81 | ||
84 | /* | 82 | /* |
85 | * Called with shm_ids.rw_mutex (writer) and the shp structure locked. | 83 | * Called with shm_ids.rw_mutex (writer) and the shp structure locked. |
86 | * Only shm_ids.rw_mutex remains locked on exit. | 84 | * Only shm_ids.rw_mutex remains locked on exit. |
87 | */ | 85 | */ |
88 | static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp) | 86 | static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) |
89 | { | 87 | { |
88 | struct shmid_kernel *shp; | ||
89 | shp = container_of(ipcp, struct shmid_kernel, shm_perm); | ||
90 | |||
90 | if (shp->shm_nattch){ | 91 | if (shp->shm_nattch){ |
91 | shp->shm_perm.mode |= SHM_DEST; | 92 | shp->shm_perm.mode |= SHM_DEST; |
92 | /* Do not find it any more */ | 93 | /* Do not find it any more */ |
@@ -96,47 +97,16 @@ static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp) | |||
96 | shm_destroy(ns, shp); | 97 | shm_destroy(ns, shp); |
97 | } | 98 | } |
98 | 99 | ||
99 | int shm_init_ns(struct ipc_namespace *ns) | 100 | #ifdef CONFIG_IPC_NS |
100 | { | ||
101 | struct ipc_ids *ids; | ||
102 | |||
103 | ids = kmalloc(sizeof(struct ipc_ids), GFP_KERNEL); | ||
104 | if (ids == NULL) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | __shm_init_ns(ns, ids); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | void shm_exit_ns(struct ipc_namespace *ns) | 101 | void shm_exit_ns(struct ipc_namespace *ns) |
112 | { | 102 | { |
113 | struct shmid_kernel *shp; | 103 | free_ipcs(ns, &shm_ids(ns), do_shm_rmid); |
114 | struct kern_ipc_perm *perm; | ||
115 | int next_id; | ||
116 | int total, in_use; | ||
117 | |||
118 | down_write(&shm_ids(ns).rw_mutex); | ||
119 | |||
120 | in_use = shm_ids(ns).in_use; | ||
121 | |||
122 | for (total = 0, next_id = 0; total < in_use; next_id++) { | ||
123 | perm = idr_find(&shm_ids(ns).ipcs_idr, next_id); | ||
124 | if (perm == NULL) | ||
125 | continue; | ||
126 | ipc_lock_by_ptr(perm); | ||
127 | shp = container_of(perm, struct shmid_kernel, shm_perm); | ||
128 | do_shm_rmid(ns, shp); | ||
129 | total++; | ||
130 | } | ||
131 | up_write(&shm_ids(ns).rw_mutex); | ||
132 | |||
133 | kfree(ns->ids[IPC_SHM_IDS]); | ||
134 | ns->ids[IPC_SHM_IDS] = NULL; | ||
135 | } | 104 | } |
105 | #endif | ||
136 | 106 | ||
137 | void __init shm_init (void) | 107 | void __init shm_init (void) |
138 | { | 108 | { |
139 | __shm_init_ns(&init_ipc_ns, &init_shm_ids); | 109 | shm_init_ns(&init_ipc_ns); |
140 | ipc_init_proc_interface("sysvipc/shm", | 110 | ipc_init_proc_interface("sysvipc/shm", |
141 | " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n", | 111 | " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n", |
142 | IPC_SHM_IDS, sysvipc_shm_proc_show); | 112 | IPC_SHM_IDS, sysvipc_shm_proc_show); |
@@ -847,7 +817,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
847 | if (err) | 817 | if (err) |
848 | goto out_unlock_up; | 818 | goto out_unlock_up; |
849 | 819 | ||
850 | do_shm_rmid(ns, shp); | 820 | do_shm_rmid(ns, &shp->shm_perm); |
851 | up_write(&shm_ids(ns).rw_mutex); | 821 | up_write(&shm_ids(ns).rw_mutex); |
852 | goto out; | 822 | goto out; |
853 | } | 823 | } |
diff --git a/ipc/util.c b/ipc/util.c index 76c1f3461e22..fd1b50da9db8 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/audit.h> | 33 | #include <linux/audit.h> |
34 | #include <linux/nsproxy.h> | 34 | #include <linux/nsproxy.h> |
35 | #include <linux/rwsem.h> | 35 | #include <linux/rwsem.h> |
36 | #include <linux/ipc_namespace.h> | ||
36 | 37 | ||
37 | #include <asm/unistd.h> | 38 | #include <asm/unistd.h> |
38 | 39 | ||
@@ -51,66 +52,6 @@ struct ipc_namespace init_ipc_ns = { | |||
51 | }, | 52 | }, |
52 | }; | 53 | }; |
53 | 54 | ||
54 | static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) | ||
55 | { | ||
56 | int err; | ||
57 | struct ipc_namespace *ns; | ||
58 | |||
59 | err = -ENOMEM; | ||
60 | ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL); | ||
61 | if (ns == NULL) | ||
62 | goto err_mem; | ||
63 | |||
64 | err = sem_init_ns(ns); | ||
65 | if (err) | ||
66 | goto err_sem; | ||
67 | err = msg_init_ns(ns); | ||
68 | if (err) | ||
69 | goto err_msg; | ||
70 | err = shm_init_ns(ns); | ||
71 | if (err) | ||
72 | goto err_shm; | ||
73 | |||
74 | kref_init(&ns->kref); | ||
75 | return ns; | ||
76 | |||
77 | err_shm: | ||
78 | msg_exit_ns(ns); | ||
79 | err_msg: | ||
80 | sem_exit_ns(ns); | ||
81 | err_sem: | ||
82 | kfree(ns); | ||
83 | err_mem: | ||
84 | return ERR_PTR(err); | ||
85 | } | ||
86 | |||
87 | struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) | ||
88 | { | ||
89 | struct ipc_namespace *new_ns; | ||
90 | |||
91 | BUG_ON(!ns); | ||
92 | get_ipc_ns(ns); | ||
93 | |||
94 | if (!(flags & CLONE_NEWIPC)) | ||
95 | return ns; | ||
96 | |||
97 | new_ns = clone_ipc_ns(ns); | ||
98 | |||
99 | put_ipc_ns(ns); | ||
100 | return new_ns; | ||
101 | } | ||
102 | |||
103 | void free_ipc_ns(struct kref *kref) | ||
104 | { | ||
105 | struct ipc_namespace *ns; | ||
106 | |||
107 | ns = container_of(kref, struct ipc_namespace, kref); | ||
108 | sem_exit_ns(ns); | ||
109 | msg_exit_ns(ns); | ||
110 | shm_exit_ns(ns); | ||
111 | kfree(ns); | ||
112 | } | ||
113 | |||
114 | /** | 55 | /** |
115 | * ipc_init - initialise IPC subsystem | 56 | * ipc_init - initialise IPC subsystem |
116 | * | 57 | * |
@@ -307,7 +248,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
307 | * This routine is called by sys_msgget, sys_semget() and sys_shmget() | 248 | * This routine is called by sys_msgget, sys_semget() and sys_shmget() |
308 | * when the key is IPC_PRIVATE. | 249 | * when the key is IPC_PRIVATE. |
309 | */ | 250 | */ |
310 | int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, | 251 | static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, |
311 | struct ipc_ops *ops, struct ipc_params *params) | 252 | struct ipc_ops *ops, struct ipc_params *params) |
312 | { | 253 | { |
313 | int err; | 254 | int err; |
@@ -371,7 +312,7 @@ static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops, | |||
371 | * | 312 | * |
372 | * On success, the ipc id is returned. | 313 | * On success, the ipc id is returned. |
373 | */ | 314 | */ |
374 | int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, | 315 | static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, |
375 | struct ipc_ops *ops, struct ipc_params *params) | 316 | struct ipc_ops *ops, struct ipc_params *params) |
376 | { | 317 | { |
377 | struct kern_ipc_perm *ipcp; | 318 | struct kern_ipc_perm *ipcp; |
@@ -769,6 +710,57 @@ struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *ids, int id) | |||
769 | return out; | 710 | return out; |
770 | } | 711 | } |
771 | 712 | ||
713 | struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, int id) | ||
714 | { | ||
715 | struct kern_ipc_perm *out; | ||
716 | |||
717 | out = ipc_lock_down(ids, id); | ||
718 | if (IS_ERR(out)) | ||
719 | return out; | ||
720 | |||
721 | if (ipc_checkid(out, id)) { | ||
722 | ipc_unlock(out); | ||
723 | return ERR_PTR(-EIDRM); | ||
724 | } | ||
725 | |||
726 | return out; | ||
727 | } | ||
728 | |||
729 | struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id) | ||
730 | { | ||
731 | struct kern_ipc_perm *out; | ||
732 | |||
733 | out = ipc_lock(ids, id); | ||
734 | if (IS_ERR(out)) | ||
735 | return out; | ||
736 | |||
737 | if (ipc_checkid(out, id)) { | ||
738 | ipc_unlock(out); | ||
739 | return ERR_PTR(-EIDRM); | ||
740 | } | ||
741 | |||
742 | return out; | ||
743 | } | ||
744 | |||
745 | /** | ||
746 | * ipcget - Common sys_*get() code | ||
747 | * @ns : namsepace | ||
748 | * @ids : IPC identifier set | ||
749 | * @ops : operations to be called on ipc object creation, permission checks | ||
750 | * and further checks | ||
751 | * @params : the parameters needed by the previous operations. | ||
752 | * | ||
753 | * Common routine called by sys_msgget(), sys_semget() and sys_shmget(). | ||
754 | */ | ||
755 | int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
756 | struct ipc_ops *ops, struct ipc_params *params) | ||
757 | { | ||
758 | if (params->key == IPC_PRIVATE) | ||
759 | return ipcget_new(ns, ids, ops, params); | ||
760 | else | ||
761 | return ipcget_public(ns, ids, ops, params); | ||
762 | } | ||
763 | |||
772 | #ifdef __ARCH_WANT_IPC_PARSE_VERSION | 764 | #ifdef __ARCH_WANT_IPC_PARSE_VERSION |
773 | 765 | ||
774 | 766 | ||
@@ -841,7 +833,7 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos) | |||
841 | if (ipc && ipc != SEQ_START_TOKEN) | 833 | if (ipc && ipc != SEQ_START_TOKEN) |
842 | ipc_unlock(ipc); | 834 | ipc_unlock(ipc); |
843 | 835 | ||
844 | return sysvipc_find_ipc(iter->ns->ids[iface->ids], *pos, pos); | 836 | return sysvipc_find_ipc(&iter->ns->ids[iface->ids], *pos, pos); |
845 | } | 837 | } |
846 | 838 | ||
847 | /* | 839 | /* |
@@ -854,7 +846,7 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos) | |||
854 | struct ipc_proc_iface *iface = iter->iface; | 846 | struct ipc_proc_iface *iface = iter->iface; |
855 | struct ipc_ids *ids; | 847 | struct ipc_ids *ids; |
856 | 848 | ||
857 | ids = iter->ns->ids[iface->ids]; | 849 | ids = &iter->ns->ids[iface->ids]; |
858 | 850 | ||
859 | /* | 851 | /* |
860 | * Take the lock - this will be released by the corresponding | 852 | * Take the lock - this will be released by the corresponding |
@@ -885,7 +877,7 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it) | |||
885 | if (ipc && ipc != SEQ_START_TOKEN) | 877 | if (ipc && ipc != SEQ_START_TOKEN) |
886 | ipc_unlock(ipc); | 878 | ipc_unlock(ipc); |
887 | 879 | ||
888 | ids = iter->ns->ids[iface->ids]; | 880 | ids = &iter->ns->ids[iface->ids]; |
889 | /* Release the lock we took in start() */ | 881 | /* Release the lock we took in start() */ |
890 | up_read(&ids->rw_mutex); | 882 | up_read(&ids->rw_mutex); |
891 | } | 883 | } |
diff --git a/ipc/util.h b/ipc/util.h index 9ffea40457ce..f37d160c98fe 100644 --- a/ipc/util.h +++ b/ipc/util.h | |||
@@ -10,7 +10,6 @@ | |||
10 | #ifndef _IPC_UTIL_H | 10 | #ifndef _IPC_UTIL_H |
11 | #define _IPC_UTIL_H | 11 | #define _IPC_UTIL_H |
12 | 12 | ||
13 | #include <linux/idr.h> | ||
14 | #include <linux/err.h> | 13 | #include <linux/err.h> |
15 | 14 | ||
16 | #define USHRT_MAX 0xffff | 15 | #define USHRT_MAX 0xffff |
@@ -20,22 +19,16 @@ void sem_init (void); | |||
20 | void msg_init (void); | 19 | void msg_init (void); |
21 | void shm_init (void); | 20 | void shm_init (void); |
22 | 21 | ||
23 | int sem_init_ns(struct ipc_namespace *ns); | 22 | struct ipc_namespace; |
24 | int msg_init_ns(struct ipc_namespace *ns); | 23 | |
25 | int shm_init_ns(struct ipc_namespace *ns); | 24 | void sem_init_ns(struct ipc_namespace *ns); |
25 | void msg_init_ns(struct ipc_namespace *ns); | ||
26 | void shm_init_ns(struct ipc_namespace *ns); | ||
26 | 27 | ||
27 | void sem_exit_ns(struct ipc_namespace *ns); | 28 | void sem_exit_ns(struct ipc_namespace *ns); |
28 | void msg_exit_ns(struct ipc_namespace *ns); | 29 | void msg_exit_ns(struct ipc_namespace *ns); |
29 | void shm_exit_ns(struct ipc_namespace *ns); | 30 | void shm_exit_ns(struct ipc_namespace *ns); |
30 | 31 | ||
31 | struct ipc_ids { | ||
32 | int in_use; | ||
33 | unsigned short seq; | ||
34 | unsigned short seq_max; | ||
35 | struct rw_semaphore rw_mutex; | ||
36 | struct idr ipcs_idr; | ||
37 | }; | ||
38 | |||
39 | /* | 32 | /* |
40 | * Structure that holds the parameters needed by the ipc operations | 33 | * Structure that holds the parameters needed by the ipc operations |
41 | * (see after) | 34 | * (see after) |
@@ -66,6 +59,7 @@ struct ipc_ops { | |||
66 | }; | 59 | }; |
67 | 60 | ||
68 | struct seq_file; | 61 | struct seq_file; |
62 | struct ipc_ids; | ||
69 | 63 | ||
70 | void ipc_init_ids(struct ipc_ids *); | 64 | void ipc_init_ids(struct ipc_ids *); |
71 | #ifdef CONFIG_PROC_FS | 65 | #ifdef CONFIG_PROC_FS |
@@ -129,10 +123,6 @@ int ipc_parse_version (int *cmd); | |||
129 | extern void free_msg(struct msg_msg *msg); | 123 | extern void free_msg(struct msg_msg *msg); |
130 | extern struct msg_msg *load_msg(const void __user *src, int len); | 124 | extern struct msg_msg *load_msg(const void __user *src, int len); |
131 | extern int store_msg(void __user *dest, struct msg_msg *msg, int len); | 125 | extern int store_msg(void __user *dest, struct msg_msg *msg, int len); |
132 | extern int ipcget_new(struct ipc_namespace *, struct ipc_ids *, | ||
133 | struct ipc_ops *, struct ipc_params *); | ||
134 | extern int ipcget_public(struct ipc_namespace *, struct ipc_ids *, | ||
135 | struct ipc_ops *, struct ipc_params *); | ||
136 | 126 | ||
137 | static inline int ipc_buildid(int id, int seq) | 127 | static inline int ipc_buildid(int id, int seq) |
138 | { | 128 | { |
@@ -161,57 +151,9 @@ static inline void ipc_unlock(struct kern_ipc_perm *perm) | |||
161 | rcu_read_unlock(); | 151 | rcu_read_unlock(); |
162 | } | 152 | } |
163 | 153 | ||
164 | static inline struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, | 154 | struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, int id); |
165 | int id) | 155 | struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id); |
166 | { | 156 | int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, |
167 | struct kern_ipc_perm *out; | 157 | struct ipc_ops *ops, struct ipc_params *params); |
168 | |||
169 | out = ipc_lock_down(ids, id); | ||
170 | if (IS_ERR(out)) | ||
171 | return out; | ||
172 | |||
173 | if (ipc_checkid(out, id)) { | ||
174 | ipc_unlock(out); | ||
175 | return ERR_PTR(-EIDRM); | ||
176 | } | ||
177 | |||
178 | return out; | ||
179 | } | ||
180 | |||
181 | static inline struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, | ||
182 | int id) | ||
183 | { | ||
184 | struct kern_ipc_perm *out; | ||
185 | |||
186 | out = ipc_lock(ids, id); | ||
187 | if (IS_ERR(out)) | ||
188 | return out; | ||
189 | |||
190 | if (ipc_checkid(out, id)) { | ||
191 | ipc_unlock(out); | ||
192 | return ERR_PTR(-EIDRM); | ||
193 | } | ||
194 | |||
195 | return out; | ||
196 | } | ||
197 | |||
198 | /** | ||
199 | * ipcget - Common sys_*get() code | ||
200 | * @ns : namsepace | ||
201 | * @ids : IPC identifier set | ||
202 | * @ops : operations to be called on ipc object creation, permission checks | ||
203 | * and further checks | ||
204 | * @params : the parameters needed by the previous operations. | ||
205 | * | ||
206 | * Common routine called by sys_msgget(), sys_semget() and sys_shmget(). | ||
207 | */ | ||
208 | static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
209 | struct ipc_ops *ops, struct ipc_params *params) | ||
210 | { | ||
211 | if (params->key == IPC_PRIVATE) | ||
212 | return ipcget_new(ns, ids, ops, params); | ||
213 | else | ||
214 | return ipcget_public(ns, ids, ops, params); | ||
215 | } | ||
216 | 158 | ||
217 | #endif | 159 | #endif |