aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorPierre Peiffer <pierre.peiffer@bull.net>2008-02-06 04:36:23 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 13:41:01 -0500
commitb1ed88b47f5e18c6efb8041275c16eeead5377df (patch)
tree3861cbdbac7289a790adf5f950c1921fb1692f6c /ipc
parent15aafa2f9d8399b22e418c53a87dfc0c43f4030f (diff)
IPC: fix error check in all new xxx_lock() and xxx_exit_ns() functions
In the new implementation of the [sem|shm|msg]_lock[_check]() routines, we use the return value of ipc_lock() in container_of() without any check. But ipc_lock may return a errcode. The use of this errcode in container_of() may alter this errcode, and we don't want this. And in xxx_exit_ns, the pointer return by idr_find is of type 'struct kern_ipc_per'... Today, the code will work as is because the member used in these container_of() is the first member of its container (offset == 0), the errcode isn't changed then. But in the general case, we can't count on this assumption and this may lead later to a real bug if we don't correct this. Again, the proposed solution is simple and correct. But, as pointed by Nadia, with this solution, the same check will be done several times (in all sub-callers...), what is not very funny/optimal... Signed-off-by: Pierre Peiffer <pierre.peiffer@bull.net> Cc: Nadia Derbey <Nadia.Derbey@bull.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/msg.c17
-rw-r--r--ipc/sem.c17
-rw-r--r--ipc/shm.c20
3 files changed, 45 insertions, 9 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index fdf3db5731ce..ec0c724054b9 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -105,6 +105,7 @@ int msg_init_ns(struct ipc_namespace *ns)
105void msg_exit_ns(struct ipc_namespace *ns) 105void msg_exit_ns(struct ipc_namespace *ns)
106{ 106{
107 struct msg_queue *msq; 107 struct msg_queue *msq;
108 struct kern_ipc_perm *perm;
108 int next_id; 109 int next_id;
109 int total, in_use; 110 int total, in_use;
110 111
@@ -113,10 +114,11 @@ void msg_exit_ns(struct ipc_namespace *ns)
113 in_use = msg_ids(ns).in_use; 114 in_use = msg_ids(ns).in_use;
114 115
115 for (total = 0, next_id = 0; total < in_use; next_id++) { 116 for (total = 0, next_id = 0; total < in_use; next_id++) {
116 msq = idr_find(&msg_ids(ns).ipcs_idr, next_id); 117 perm = idr_find(&msg_ids(ns).ipcs_idr, next_id);
117 if (msq == NULL) 118 if (perm == NULL)
118 continue; 119 continue;
119 ipc_lock_by_ptr(&msq->q_perm); 120 ipc_lock_by_ptr(perm);
121 msq = container_of(perm, struct msg_queue, q_perm);
120 freeque(ns, msq); 122 freeque(ns, msq);
121 total++; 123 total++;
122 } 124 }
@@ -144,6 +146,9 @@ static inline struct msg_queue *msg_lock_check_down(struct ipc_namespace *ns,
144{ 146{
145 struct kern_ipc_perm *ipcp = ipc_lock_check_down(&msg_ids(ns), id); 147 struct kern_ipc_perm *ipcp = ipc_lock_check_down(&msg_ids(ns), id);
146 148
149 if (IS_ERR(ipcp))
150 return (struct msg_queue *)ipcp;
151
147 return container_of(ipcp, struct msg_queue, q_perm); 152 return container_of(ipcp, struct msg_queue, q_perm);
148} 153}
149 154
@@ -155,6 +160,9 @@ static inline struct msg_queue *msg_lock(struct ipc_namespace *ns, int id)
155{ 160{
156 struct kern_ipc_perm *ipcp = ipc_lock(&msg_ids(ns), id); 161 struct kern_ipc_perm *ipcp = ipc_lock(&msg_ids(ns), id);
157 162
163 if (IS_ERR(ipcp))
164 return (struct msg_queue *)ipcp;
165
158 return container_of(ipcp, struct msg_queue, q_perm); 166 return container_of(ipcp, struct msg_queue, q_perm);
159} 167}
160 168
@@ -163,6 +171,9 @@ static inline struct msg_queue *msg_lock_check(struct ipc_namespace *ns,
163{ 171{
164 struct kern_ipc_perm *ipcp = ipc_lock_check(&msg_ids(ns), id); 172 struct kern_ipc_perm *ipcp = ipc_lock_check(&msg_ids(ns), id);
165 173
174 if (IS_ERR(ipcp))
175 return (struct msg_queue *)ipcp;
176
166 return container_of(ipcp, struct msg_queue, q_perm); 177 return container_of(ipcp, struct msg_queue, q_perm);
167} 178}
168 179
diff --git a/ipc/sem.c b/ipc/sem.c
index 35952c0bae46..d65e285b7e30 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -143,6 +143,7 @@ int sem_init_ns(struct ipc_namespace *ns)
143void sem_exit_ns(struct ipc_namespace *ns) 143void sem_exit_ns(struct ipc_namespace *ns)
144{ 144{
145 struct sem_array *sma; 145 struct sem_array *sma;
146 struct kern_ipc_perm *perm;
146 int next_id; 147 int next_id;
147 int total, in_use; 148 int total, in_use;
148 149
@@ -151,10 +152,11 @@ void sem_exit_ns(struct ipc_namespace *ns)
151 in_use = sem_ids(ns).in_use; 152 in_use = sem_ids(ns).in_use;
152 153
153 for (total = 0, next_id = 0; total < in_use; next_id++) { 154 for (total = 0, next_id = 0; total < in_use; next_id++) {
154 sma = idr_find(&sem_ids(ns).ipcs_idr, next_id); 155 perm = idr_find(&sem_ids(ns).ipcs_idr, next_id);
155 if (sma == NULL) 156 if (perm == NULL)
156 continue; 157 continue;
157 ipc_lock_by_ptr(&sma->sem_perm); 158 ipc_lock_by_ptr(perm);
159 sma = container_of(perm, struct sem_array, sem_perm);
158 freeary(ns, sma); 160 freeary(ns, sma);
159 total++; 161 total++;
160 } 162 }
@@ -181,6 +183,9 @@ static inline struct sem_array *sem_lock_check_down(struct ipc_namespace *ns,
181{ 183{
182 struct kern_ipc_perm *ipcp = ipc_lock_check_down(&sem_ids(ns), id); 184 struct kern_ipc_perm *ipcp = ipc_lock_check_down(&sem_ids(ns), id);
183 185
186 if (IS_ERR(ipcp))
187 return (struct sem_array *)ipcp;
188
184 return container_of(ipcp, struct sem_array, sem_perm); 189 return container_of(ipcp, struct sem_array, sem_perm);
185} 190}
186 191
@@ -192,6 +197,9 @@ static inline struct sem_array *sem_lock(struct ipc_namespace *ns, int id)
192{ 197{
193 struct kern_ipc_perm *ipcp = ipc_lock(&sem_ids(ns), id); 198 struct kern_ipc_perm *ipcp = ipc_lock(&sem_ids(ns), id);
194 199
200 if (IS_ERR(ipcp))
201 return (struct sem_array *)ipcp;
202
195 return container_of(ipcp, struct sem_array, sem_perm); 203 return container_of(ipcp, struct sem_array, sem_perm);
196} 204}
197 205
@@ -200,6 +208,9 @@ static inline struct sem_array *sem_lock_check(struct ipc_namespace *ns,
200{ 208{
201 struct kern_ipc_perm *ipcp = ipc_lock_check(&sem_ids(ns), id); 209 struct kern_ipc_perm *ipcp = ipc_lock_check(&sem_ids(ns), id);
202 210
211 if (IS_ERR(ipcp))
212 return (struct sem_array *)ipcp;
213
203 return container_of(ipcp, struct sem_array, sem_perm); 214 return container_of(ipcp, struct sem_array, sem_perm);
204} 215}
205 216
diff --git a/ipc/shm.c b/ipc/shm.c
index 3818fae625c5..65c3a294aba5 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -111,6 +111,7 @@ int shm_init_ns(struct ipc_namespace *ns)
111void shm_exit_ns(struct ipc_namespace *ns) 111void shm_exit_ns(struct ipc_namespace *ns)
112{ 112{
113 struct shmid_kernel *shp; 113 struct shmid_kernel *shp;
114 struct kern_ipc_perm *perm;
114 int next_id; 115 int next_id;
115 int total, in_use; 116 int total, in_use;
116 117
@@ -119,10 +120,11 @@ void shm_exit_ns(struct ipc_namespace *ns)
119 in_use = shm_ids(ns).in_use; 120 in_use = shm_ids(ns).in_use;
120 121
121 for (total = 0, next_id = 0; total < in_use; next_id++) { 122 for (total = 0, next_id = 0; total < in_use; next_id++) {
122 shp = idr_find(&shm_ids(ns).ipcs_idr, next_id); 123 perm = idr_find(&shm_ids(ns).ipcs_idr, next_id);
123 if (shp == NULL) 124 if (perm == NULL)
124 continue; 125 continue;
125 ipc_lock_by_ptr(&shp->shm_perm); 126 ipc_lock_by_ptr(perm);
127 shp = container_of(perm, struct shmid_kernel, shm_perm);
126 do_shm_rmid(ns, shp); 128 do_shm_rmid(ns, shp);
127 total++; 129 total++;
128 } 130 }
@@ -149,6 +151,9 @@ static inline struct shmid_kernel *shm_lock_down(struct ipc_namespace *ns,
149{ 151{
150 struct kern_ipc_perm *ipcp = ipc_lock_down(&shm_ids(ns), id); 152 struct kern_ipc_perm *ipcp = ipc_lock_down(&shm_ids(ns), id);
151 153
154 if (IS_ERR(ipcp))
155 return (struct shmid_kernel *)ipcp;
156
152 return container_of(ipcp, struct shmid_kernel, shm_perm); 157 return container_of(ipcp, struct shmid_kernel, shm_perm);
153} 158}
154 159
@@ -158,6 +163,9 @@ static inline struct shmid_kernel *shm_lock_check_down(
158{ 163{
159 struct kern_ipc_perm *ipcp = ipc_lock_check_down(&shm_ids(ns), id); 164 struct kern_ipc_perm *ipcp = ipc_lock_check_down(&shm_ids(ns), id);
160 165
166 if (IS_ERR(ipcp))
167 return (struct shmid_kernel *)ipcp;
168
161 return container_of(ipcp, struct shmid_kernel, shm_perm); 169 return container_of(ipcp, struct shmid_kernel, shm_perm);
162} 170}
163 171
@@ -169,6 +177,9 @@ static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
169{ 177{
170 struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id); 178 struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id);
171 179
180 if (IS_ERR(ipcp))
181 return (struct shmid_kernel *)ipcp;
182
172 return container_of(ipcp, struct shmid_kernel, shm_perm); 183 return container_of(ipcp, struct shmid_kernel, shm_perm);
173} 184}
174 185
@@ -177,6 +188,9 @@ static inline struct shmid_kernel *shm_lock_check(struct ipc_namespace *ns,
177{ 188{
178 struct kern_ipc_perm *ipcp = ipc_lock_check(&shm_ids(ns), id); 189 struct kern_ipc_perm *ipcp = ipc_lock_check(&shm_ids(ns), id);
179 190
191 if (IS_ERR(ipcp))
192 return (struct shmid_kernel *)ipcp;
193
180 return container_of(ipcp, struct shmid_kernel, shm_perm); 194 return container_of(ipcp, struct shmid_kernel, shm_perm);
181} 195}
182 196