diff options
Diffstat (limited to 'ipc/util.c')
-rw-r--r-- | ipc/util.c | 122 |
1 files changed, 57 insertions, 65 deletions
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 | } |