aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c162
1 files changed, 1 insertions, 161 deletions
diff --git a/fs/compat.c b/fs/compat.c
index a32e2ae737fb..9f6248dfd9d9 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -25,10 +25,8 @@
25#include <linux/namei.h> 25#include <linux/namei.h>
26#include <linux/file.h> 26#include <linux/file.h>
27#include <linux/vfs.h> 27#include <linux/vfs.h>
28#include <linux/ioctl32.h>
29#include <linux/ioctl.h> 28#include <linux/ioctl.h>
30#include <linux/init.h> 29#include <linux/init.h>
31#include <linux/sockios.h> /* for SIOCDEVPRIVATE */
32#include <linux/smb.h> 30#include <linux/smb.h>
33#include <linux/smb_mount.h> 31#include <linux/smb_mount.h>
34#include <linux/ncp_mount.h> 32#include <linux/ncp_mount.h>
@@ -46,13 +44,12 @@
46#include <linux/personality.h> 44#include <linux/personality.h>
47#include <linux/rwsem.h> 45#include <linux/rwsem.h>
48#include <linux/tsacct_kern.h> 46#include <linux/tsacct_kern.h>
47#include <linux/security.h>
49#include <linux/highmem.h> 48#include <linux/highmem.h>
50#include <linux/poll.h> 49#include <linux/poll.h>
51#include <linux/mm.h> 50#include <linux/mm.h>
52#include <linux/eventpoll.h> 51#include <linux/eventpoll.h>
53 52
54#include <net/sock.h> /* siocdevprivate_ioctl */
55
56#include <asm/uaccess.h> 53#include <asm/uaccess.h>
57#include <asm/mmu_context.h> 54#include <asm/mmu_context.h>
58#include <asm/ioctls.h> 55#include <asm/ioctls.h>
@@ -313,163 +310,6 @@ out:
313 return error; 310 return error;
314} 311}
315 312
316/* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64, MIPS */
317
318#define IOCTL_HASHSIZE 256
319static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
320
321static inline unsigned long ioctl32_hash(unsigned long cmd)
322{
323 return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE;
324}
325
326static void ioctl32_insert_translation(struct ioctl_trans *trans)
327{
328 unsigned long hash;
329 struct ioctl_trans *t;
330
331 hash = ioctl32_hash (trans->cmd);
332 if (!ioctl32_hash_table[hash])
333 ioctl32_hash_table[hash] = trans;
334 else {
335 t = ioctl32_hash_table[hash];
336 while (t->next)
337 t = t->next;
338 trans->next = NULL;
339 t->next = trans;
340 }
341}
342
343static int __init init_sys32_ioctl(void)
344{
345 int i;
346
347 for (i = 0; i < ioctl_table_size; i++) {
348 if (ioctl_start[i].next != 0) {
349 printk("ioctl translation %d bad\n",i);
350 return -1;
351 }
352
353 ioctl32_insert_translation(&ioctl_start[i]);
354 }
355 return 0;
356}
357
358__initcall(init_sys32_ioctl);
359
360static void compat_ioctl_error(struct file *filp, unsigned int fd,
361 unsigned int cmd, unsigned long arg)
362{
363 char buf[10];
364 char *fn = "?";
365 char *path;
366
367 /* find the name of the device. */
368 path = (char *)__get_free_page(GFP_KERNEL);
369 if (path) {
370 fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
371 if (IS_ERR(fn))
372 fn = "?";
373 }
374
375 sprintf(buf,"'%c'", (cmd>>_IOC_TYPESHIFT) & _IOC_TYPEMASK);
376 if (!isprint(buf[1]))
377 sprintf(buf, "%02x", buf[1]);
378 compat_printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
379 "cmd(%08x){t:%s;sz:%u} arg(%08x) on %s\n",
380 current->comm, current->pid,
381 (int)fd, (unsigned int)cmd, buf,
382 (cmd >> _IOC_SIZESHIFT) & _IOC_SIZEMASK,
383 (unsigned int)arg, fn);
384
385 if (path)
386 free_page((unsigned long)path);
387}
388
389asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
390 unsigned long arg)
391{
392 struct file *filp;
393 int error = -EBADF;
394 struct ioctl_trans *t;
395 int fput_needed;
396
397 filp = fget_light(fd, &fput_needed);
398 if (!filp)
399 goto out;
400
401 /* RED-PEN how should LSM module know it's handling 32bit? */
402 error = security_file_ioctl(filp, cmd, arg);
403 if (error)
404 goto out_fput;
405
406 /*
407 * To allow the compat_ioctl handlers to be self contained
408 * we need to check the common ioctls here first.
409 * Just handle them with the standard handlers below.
410 */
411 switch (cmd) {
412 case FIOCLEX:
413 case FIONCLEX:
414 case FIONBIO:
415 case FIOASYNC:
416 case FIOQSIZE:
417 break;
418
419 case FIBMAP:
420 case FIGETBSZ:
421 case FIONREAD:
422 if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
423 break;
424 /*FALL THROUGH*/
425
426 default:
427 if (filp->f_op && filp->f_op->compat_ioctl) {
428 error = filp->f_op->compat_ioctl(filp, cmd, arg);
429 if (error != -ENOIOCTLCMD)
430 goto out_fput;
431 }
432
433 if (!filp->f_op ||
434 (!filp->f_op->ioctl && !filp->f_op->unlocked_ioctl))
435 goto do_ioctl;
436 break;
437 }
438
439 for (t = ioctl32_hash_table[ioctl32_hash(cmd)]; t; t = t->next) {
440 if (t->cmd == cmd)
441 goto found_handler;
442 }
443
444 if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
445 cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
446 error = siocdevprivate_ioctl(fd, cmd, arg);
447 } else {
448 static int count;
449
450 if (++count <= 50)
451 compat_ioctl_error(filp, fd, cmd, arg);
452 error = -EINVAL;
453 }
454
455 goto out_fput;
456
457 found_handler:
458 if (t->handler) {
459 lock_kernel();
460 error = t->handler(fd, cmd, arg, filp);
461 unlock_kernel();
462 goto out_fput;
463 }
464
465 do_ioctl:
466 error = vfs_ioctl(filp, fd, cmd, arg);
467 out_fput:
468 fput_light(filp, fput_needed);
469 out:
470 return error;
471}
472
473static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) 313static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
474{ 314{
475 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || 315 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||