aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm/resources.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/atm/resources.c')
-rw-r--r--net/atm/resources.c88
1 files changed, 68 insertions, 20 deletions
diff --git a/net/atm/resources.c b/net/atm/resources.c
index a34ba948af96..56b7322ff461 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -195,20 +195,39 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, in
195} 195}
196 196
197 197
198int atm_dev_ioctl(unsigned int cmd, void __user *arg) 198int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
199{ 199{
200 void __user *buf; 200 void __user *buf;
201 int error, len, number, size = 0; 201 int error, len, number, size = 0;
202 struct atm_dev *dev; 202 struct atm_dev *dev;
203 struct list_head *p; 203 struct list_head *p;
204 int *tmp_buf, *tmp_p; 204 int *tmp_buf, *tmp_p;
205 struct atm_iobuf __user *iobuf = arg; 205 int __user *sioc_len;
206 struct atmif_sioc __user *sioc = arg; 206 int __user *iobuf_len;
207
208#ifndef CONFIG_COMPAT
209 compat = 0; /* Just so the compiler _knows_ */
210#endif
211
207 switch (cmd) { 212 switch (cmd) {
208 case ATM_GETNAMES: 213 case ATM_GETNAMES:
209 if (get_user(buf, &iobuf->buffer)) 214
210 return -EFAULT; 215 if (compat) {
211 if (get_user(len, &iobuf->length)) 216#ifdef CONFIG_COMPAT
217 struct compat_atm_iobuf __user *ciobuf = arg;
218 compat_uptr_t cbuf;
219 iobuf_len = &ciobuf->length;
220 if (get_user(cbuf, &ciobuf->buffer))
221 return -EFAULT;
222 buf = compat_ptr(cbuf);
223#endif
224 } else {
225 struct atm_iobuf __user *iobuf = arg;
226 iobuf_len = &iobuf->length;
227 if (get_user(buf, &iobuf->buffer))
228 return -EFAULT;
229 }
230 if (get_user(len, iobuf_len))
212 return -EFAULT; 231 return -EFAULT;
213 mutex_lock(&atm_dev_mutex); 232 mutex_lock(&atm_dev_mutex);
214 list_for_each(p, &atm_devs) 233 list_for_each(p, &atm_devs)
@@ -229,7 +248,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
229 } 248 }
230 mutex_unlock(&atm_dev_mutex); 249 mutex_unlock(&atm_dev_mutex);
231 error = ((copy_to_user(buf, tmp_buf, size)) || 250 error = ((copy_to_user(buf, tmp_buf, size)) ||
232 put_user(size, &iobuf->length)) 251 put_user(size, iobuf_len))
233 ? -EFAULT : 0; 252 ? -EFAULT : 0;
234 kfree(tmp_buf); 253 kfree(tmp_buf);
235 return error; 254 return error;
@@ -237,13 +256,32 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
237 break; 256 break;
238 } 257 }
239 258
240 if (get_user(buf, &sioc->arg)) 259 if (compat) {
241 return -EFAULT; 260#ifdef CONFIG_COMPAT
242 if (get_user(len, &sioc->length)) 261 struct compat_atmif_sioc __user *csioc = arg;
243 return -EFAULT; 262 compat_uptr_t carg;
244 if (get_user(number, &sioc->number)) 263
245 return -EFAULT; 264 sioc_len = &csioc->length;
246 265 if (get_user(carg, &csioc->arg))
266 return -EFAULT;
267 buf = compat_ptr(carg);
268
269 if (get_user(len, &csioc->length))
270 return -EFAULT;
271 if (get_user(number, &csioc->number))
272 return -EFAULT;
273#endif
274 } else {
275 struct atmif_sioc __user *sioc = arg;
276
277 sioc_len = &sioc->length;
278 if (get_user(buf, &sioc->arg))
279 return -EFAULT;
280 if (get_user(len, &sioc->length))
281 return -EFAULT;
282 if (get_user(number, &sioc->number))
283 return -EFAULT;
284 }
247 if (!(dev = try_then_request_module(atm_dev_lookup(number), 285 if (!(dev = try_then_request_module(atm_dev_lookup(number),
248 "atm-device-%d", number))) 286 "atm-device-%d", number)))
249 return -ENODEV; 287 return -ENODEV;
@@ -358,7 +396,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
358 size = error; 396 size = error;
359 /* may return 0, but later on size == 0 means "don't 397 /* may return 0, but later on size == 0 means "don't
360 write the length" */ 398 write the length" */
361 error = put_user(size, &sioc->length) 399 error = put_user(size, sioc_len)
362 ? -EFAULT : 0; 400 ? -EFAULT : 0;
363 goto done; 401 goto done;
364 case ATM_SETLOOP: 402 case ATM_SETLOOP:
@@ -380,11 +418,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
380 } 418 }
381 /* fall through */ 419 /* fall through */
382 default: 420 default:
383 if (!dev->ops->ioctl) { 421 if (compat) {
384 error = -EINVAL; 422#ifdef CONFIG_COMPAT
385 goto done; 423 if (!dev->ops->compat_ioctl) {
424 error = -EINVAL;
425 goto done;
426 }
427 size = dev->ops->compat_ioctl(dev, cmd, buf);
428#endif
429 } else {
430 if (!dev->ops->ioctl) {
431 error = -EINVAL;
432 goto done;
433 }
434 size = dev->ops->ioctl(dev, cmd, buf);
386 } 435 }
387 size = dev->ops->ioctl(dev, cmd, buf);
388 if (size < 0) { 436 if (size < 0) {
389 error = (size == -ENOIOCTLCMD ? -EINVAL : size); 437 error = (size == -ENOIOCTLCMD ? -EINVAL : size);
390 goto done; 438 goto done;
@@ -392,7 +440,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
392 } 440 }
393 441
394 if (size) 442 if (size)
395 error = put_user(size, &sioc->length) 443 error = put_user(size, sioc_len)
396 ? -EFAULT : 0; 444 ? -EFAULT : 0;
397 else 445 else
398 error = 0; 446 error = 0;