aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm/resources.c
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2008-12-04 01:12:38 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-04 01:12:38 -0500
commit8865c418caf4e9dd2c24bdfae3a5a4106e143e60 (patch)
tree4d7fac2c74af56c6aaf83b324b349b76c5f949d9 /net/atm/resources.c
parentdcd39c90290297f6e6ed8a04bb20da7ac2b043c5 (diff)
atm: 32-bit ioctl compatibility
We lack compat ioctl support through most of the ATM code. This patch deals with most of it, and I can now at least use BR2684 and PPPoATM with 32-bit userspace. I haven't added a .compat_ioctl method to struct atm_ioctl, because AFAICT none of the current users need any conversion -- so we can just call the ->ioctl() method in every case. I looked at br2684, clip, lec, mpc, pppoatm and atmtcp. In svc_compat_ioctl() the only mangling which is needed is to change COMPAT_ATM_ADDPARTY to ATM_ADDPARTY. Although it's defined as _IOW('a', ATMIOC_SPECIAL+4,struct atm_iobuf) it doesn't actually _take_ a struct atm_iobuf as an argument -- it takes a struct sockaddr_atmsvc, which _is_ the same between 32-bit and 64-bit code, so doesn't need conversion. Almost all of vcc_ioctl() would have been identical, so I converted that into a core do_vcc_ioctl() function with an 'int compat' argument. I've done the same with atm_dev_ioctl(), where there _are_ a few differences, but still it's relatively contained and there would otherwise have been a lot of duplication. I haven't done any of the actual device-specific ioctls, although I've added a compat_ioctl method to struct atmdev_ops. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
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;