RHEL4/fs/compat_ioctl.c
<<
>>
Prefs
   1/*
   2 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
   3 *
   4 * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
   5 * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
   6 * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs 
   7 * Copyright (C) 2003       Pavel Machek (pavel@suse.cz)
   8 *
   9 * These routines maintain argument size conversion between 32bit and 64bit
  10 * ioctls.
  11 */
  12
  13#ifdef INCLUDES
  14#include <linux/config.h>
  15#include <linux/types.h>
  16#include <linux/compat.h>
  17#include <linux/kernel.h>
  18#include <linux/compiler.h>
  19#include <linux/sched.h>
  20#include <linux/smp.h>
  21#include <linux/smp_lock.h>
  22#include <linux/ioctl.h>
  23#include <linux/if.h>
  24#include <linux/if_bridge.h>
  25#include <linux/slab.h>
  26#include <linux/hdreg.h>
  27#include <linux/raid/md.h>
  28#include <linux/kd.h>
  29#include <linux/dirent.h>
  30#include <linux/route.h>
  31#include <linux/in6.h>
  32#include <linux/ipv6_route.h>
  33#include <linux/skbuff.h>
  34#include <linux/netlink.h>
  35#include <linux/vt.h>
  36#include <linux/fs.h>
  37#include <linux/file.h>
  38#include <linux/fd.h>
  39#include <linux/ppp_defs.h>
  40#include <linux/if_ppp.h>
  41#include <linux/if_pppox.h>
  42#include <linux/mtio.h>
  43#include <linux/cdrom.h>
  44#include <linux/loop.h>
  45#include <linux/auto_fs.h>
  46#include <linux/auto_fs4.h>
  47#include <linux/devfs_fs.h>
  48#include <linux/tty.h>
  49#include <linux/vt_kern.h>
  50#include <linux/fb.h>
  51#include <linux/ext2_fs.h>
  52#include <linux/ext3_jbd.h>
  53#include <linux/ext3_fs.h>
  54#include <linux/videodev.h>
  55#include <linux/netdevice.h>
  56#include <linux/raw.h>
  57#include <linux/smb_fs.h>
  58#include <linux/blkpg.h>
  59#include <linux/blkdev.h>
  60#include <linux/elevator.h>
  61#include <linux/rtc.h>
  62#include <linux/pci.h>
  63#include <linux/module.h>
  64#include <linux/serial.h>
  65#include <linux/reiserfs_fs.h>
  66#include <linux/if_tun.h>
  67#include <linux/ctype.h>
  68#include <linux/ioctl32.h>
  69#include <linux/syscalls.h>
  70#include <linux/ncp_fs.h>
  71#include <linux/i2c.h>
  72#include <linux/i2c-dev.h>
  73#include <linux/wireless.h>
  74
  75#include <net/sock.h>          /* siocdevprivate_ioctl */
  76#include <net/bluetooth/bluetooth.h>
  77#include <net/bluetooth/hci.h>
  78#include <net/bluetooth/rfcomm.h>
  79
  80#include <linux/capi.h>
  81
  82#include <scsi/scsi.h>
  83/* Ugly hack. */
  84#undef __KERNEL__
  85#include <scsi/scsi_ioctl.h>
  86#define __KERNEL__
  87#include <scsi/sg.h>
  88
  89#include <asm/types.h>
  90#include <asm/uaccess.h>
  91#include <linux/ethtool.h>
  92#include <linux/mii.h>
  93#include <linux/if_bonding.h>
  94#include <linux/watchdog.h>
  95#include <linux/dm-ioctl.h>
  96
  97#include <asm/module.h>
  98#include <linux/soundcard.h>
  99#include <linux/lp.h>
 100
 101#include <linux/atm.h>
 102#include <linux/atmarp.h>
 103#include <linux/atmclip.h>
 104#include <linux/atmdev.h>
 105#include <linux/atmioc.h>
 106#include <linux/atmlec.h>
 107#include <linux/atmmpc.h>
 108#include <linux/atmsvc.h>
 109#include <linux/atm_tcp.h>
 110#include <linux/sonet.h>
 111#include <linux/atm_suni.h>
 112#include <linux/mtd/mtd.h>
 113
 114#include <linux/usb.h>
 115#include <linux/usbdevice_fs.h>
 116#include <linux/nbd.h>
 117#include <linux/random.h>
 118#include <linux/filter.h>
 119#include <linux/msdos_fs.h>
 120
 121#include <linux/hiddev.h>
 122
 123#undef INCLUDES
 124#endif
 125
 126#ifdef CODE
 127
 128/* Aiee. Someone does not find a difference between int and long */
 129#define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
 130#define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
 131#define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
 132#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
 133#define EXT3_IOC32_GROUP_EXTEND           _IOW('f', 7, unsigned int)
 134
 135static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
 136{
 137        mm_segment_t old_fs = get_fs();
 138        int err;
 139        unsigned long val;
 140        
 141        set_fs (KERNEL_DS);
 142        err = sys_ioctl(fd, cmd, (unsigned long)&val);
 143        set_fs (old_fs);
 144        if (!err && put_user(val, (u32 __user *)compat_ptr(arg)))
 145                return -EFAULT;
 146        return err;
 147}
 148 
 149static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
 150{
 151        mm_segment_t old_fs = get_fs();
 152        u32 __user *argptr = compat_ptr(arg);
 153        int err;
 154        unsigned long val;
 155        
 156        if(get_user(val, argptr))
 157                return -EFAULT;
 158        set_fs (KERNEL_DS);
 159        err = sys_ioctl(fd, cmd, (unsigned long)&val);
 160        set_fs (old_fs);
 161        if (!err && put_user(val, argptr))
 162                return -EFAULT;
 163        return err;
 164}
 165
 166static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 167{
 168        /* These are just misnamed, they actually get/put from/to user an int */
 169        switch (cmd) {
 170        case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
 171        case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
 172        case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
 173        case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
 174        }
 175        return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
 176}
 177
 178static int do_ext3_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 179{
 180        /* These are just misnamed, they actually get/put from/to user an int */
 181        switch (cmd) {
 182        case EXT3_IOC32_GROUP_EXTEND: cmd = EXT3_IOC_GROUP_EXTEND; break;
 183        }
 184        return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
 185}
 186
 187struct video_tuner32 {
 188        compat_int_t tuner;
 189        char name[32];
 190        compat_ulong_t rangelow, rangehigh;
 191        u32 flags;      /* It is really u32 in videodev.h */
 192        u16 mode, signal;
 193};
 194
 195static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
 196{
 197        int i;
 198
 199        if(get_user(kp->tuner, &up->tuner))
 200                return -EFAULT;
 201        for(i = 0; i < 32; i++)
 202                __get_user(kp->name[i], &up->name[i]);
 203        __get_user(kp->rangelow, &up->rangelow);
 204        __get_user(kp->rangehigh, &up->rangehigh);
 205        __get_user(kp->flags, &up->flags);
 206        __get_user(kp->mode, &up->mode);
 207        __get_user(kp->signal, &up->signal);
 208        return 0;
 209}
 210
 211static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
 212{
 213        int i;
 214
 215        if(put_user(kp->tuner, &up->tuner))
 216                return -EFAULT;
 217        for(i = 0; i < 32; i++)
 218                __put_user(kp->name[i], &up->name[i]);
 219        __put_user(kp->rangelow, &up->rangelow);
 220        __put_user(kp->rangehigh, &up->rangehigh);
 221        __put_user(kp->flags, &up->flags);
 222        __put_user(kp->mode, &up->mode);
 223        __put_user(kp->signal, &up->signal);
 224        return 0;
 225}
 226
 227struct video_buffer32 {
 228        compat_caddr_t base;
 229        compat_int_t height, width, depth, bytesperline;
 230};
 231
 232static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
 233{
 234        u32 tmp;
 235
 236        if (get_user(tmp, &up->base))
 237                return -EFAULT;
 238
 239        /* This is actually a physical address stored
 240         * as a void pointer.
 241         */
 242        kp->base = (void *)(unsigned long) tmp;
 243
 244        __get_user(kp->height, &up->height);
 245        __get_user(kp->width, &up->width);
 246        __get_user(kp->depth, &up->depth);
 247        __get_user(kp->bytesperline, &up->bytesperline);
 248        return 0;
 249}
 250
 251static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
 252{
 253        u32 tmp = (u32)((unsigned long)kp->base);
 254
 255        if(put_user(tmp, &up->base))
 256                return -EFAULT;
 257        __put_user(kp->height, &up->height);
 258        __put_user(kp->width, &up->width);
 259        __put_user(kp->depth, &up->depth);
 260        __put_user(kp->bytesperline, &up->bytesperline);
 261        return 0;
 262}
 263
 264struct video_clip32 {
 265        s32 x, y, width, height;        /* Its really s32 in videodev.h */
 266        compat_caddr_t next;
 267};
 268
 269struct video_window32 {
 270        u32 x, y, width, height, chromakey, flags;
 271        compat_caddr_t clips;
 272        compat_int_t clipcount;
 273};
 274
 275/* You get back everything except the clips... */
 276static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
 277{
 278        if(put_user(kp->x, &up->x))
 279                return -EFAULT;
 280        __put_user(kp->y, &up->y);
 281        __put_user(kp->width, &up->width);
 282        __put_user(kp->height, &up->height);
 283        __put_user(kp->chromakey, &up->chromakey);
 284        __put_user(kp->flags, &up->flags);
 285        __put_user(kp->clipcount, &up->clipcount);
 286        return 0;
 287}
 288
 289#define VIDIOCGTUNER32          _IOWR('v',4, struct video_tuner32)
 290#define VIDIOCSTUNER32          _IOW('v',5, struct video_tuner32)
 291#define VIDIOCGWIN32            _IOR('v',9, struct video_window32)
 292#define VIDIOCSWIN32            _IOW('v',10, struct video_window32)
 293#define VIDIOCGFBUF32           _IOR('v',11, struct video_buffer32)
 294#define VIDIOCSFBUF32           _IOW('v',12, struct video_buffer32)
 295#define VIDIOCGFREQ32           _IOR('v',14, u32)
 296#define VIDIOCSFREQ32           _IOW('v',15, u32)
 297
 298enum {
 299        MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
 300};
 301
 302static int do_set_window(unsigned int fd, unsigned int cmd, unsigned long arg)
 303{
 304        struct video_window32 __user *up = compat_ptr(arg);
 305        struct video_window __user *vw;
 306        struct video_clip __user *p;
 307        int nclips;
 308        u32 n;
 309
 310        if (get_user(nclips, &up->clipcount))
 311                return -EFAULT;
 312
 313        /* Peculiar interface... */
 314        if (nclips < 0)
 315                nclips = VIDEO_CLIPMAP_SIZE;
 316
 317        if (nclips > MaxClips)
 318                return -ENOMEM;
 319
 320        vw = compat_alloc_user_space(sizeof(struct video_window) +
 321                                    nclips * sizeof(struct video_clip));
 322
 323        p = nclips ? (struct video_clip __user *)(vw + 1) : NULL;
 324
 325        if (get_user(n, &up->x) || put_user(n, &vw->x) ||
 326            get_user(n, &up->y) || put_user(n, &vw->y) ||
 327            get_user(n, &up->width) || put_user(n, &vw->width) ||
 328            get_user(n, &up->height) || put_user(n, &vw->height) ||
 329            get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) ||
 330            get_user(n, &up->flags) || put_user(n, &vw->flags) ||
 331            get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) ||
 332            get_user(n, &up->clips) || put_user(p, &vw->clips))
 333                return -EFAULT;
 334
 335        if (nclips) {
 336                struct video_clip32 __user *u = compat_ptr(n);
 337                int i;
 338                if (!u)
 339                        return -EINVAL;
 340                for (i = 0; i < nclips; i++, u++, p++) {
 341                        s32 v;
 342                        if (get_user(v, &u->x) ||
 343                            put_user(v, &p->x) ||
 344                            get_user(v, &u->y) ||
 345                            put_user(v, &p->y) ||
 346                            get_user(v, &u->width) ||
 347                            put_user(v, &p->width) ||
 348                            get_user(v, &u->height) ||
 349                            put_user(v, &p->height) ||
 350                            put_user(NULL, &p->next))
 351                                return -EFAULT;
 352                }
 353        }
 354
 355        return sys_ioctl(fd, VIDIOCSWIN, (unsigned long)p);
 356}
 357
 358static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 359{
 360        union {
 361                struct video_tuner vt;
 362                struct video_buffer vb;
 363                struct video_window vw;
 364                unsigned long vx;
 365        } karg;
 366        mm_segment_t old_fs = get_fs();
 367        void __user *up = compat_ptr(arg);
 368        int err = 0;
 369
 370        /* First, convert the command. */
 371        switch(cmd) {
 372        case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
 373        case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
 374        case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
 375        case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
 376        case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
 377        case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
 378        case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
 379        };
 380
 381        switch(cmd) {
 382        case VIDIOCSTUNER:
 383        case VIDIOCGTUNER:
 384                err = get_video_tuner32(&karg.vt, up);
 385                break;
 386
 387        case VIDIOCSFBUF:
 388                err = get_video_buffer32(&karg.vb, up);
 389                break;
 390
 391        case VIDIOCSFREQ:
 392                err = get_user(karg.vx, (u32 __user *)up);
 393                break;
 394        };
 395        if(err)
 396                goto out;
 397
 398        set_fs(KERNEL_DS);
 399        err = sys_ioctl(fd, cmd, (unsigned long)&karg);
 400        set_fs(old_fs);
 401
 402        if(err == 0) {
 403                switch(cmd) {
 404                case VIDIOCGTUNER:
 405                        err = put_video_tuner32(&karg.vt, up);
 406                        break;
 407
 408                case VIDIOCGWIN:
 409                        err = put_video_window32(&karg.vw, up);
 410                        break;
 411
 412                case VIDIOCGFBUF:
 413                        err = put_video_buffer32(&karg.vb, up);
 414                        break;
 415
 416                case VIDIOCGFREQ:
 417                        err = put_user(((u32)karg.vx), (u32 __user *)up);
 418                        break;
 419                };
 420        }
 421out:
 422        return err;
 423}
 424
 425#ifdef CONFIG_NET
 426static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
 427{
 428        struct compat_timeval __user *up = compat_ptr(arg);
 429        struct timeval ktv;
 430        mm_segment_t old_fs = get_fs();
 431        int err;
 432
 433        set_fs(KERNEL_DS);
 434        err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
 435        set_fs(old_fs);
 436        if(!err) {
 437                err = put_user(ktv.tv_sec, &up->tv_sec);
 438                err |= __put_user(ktv.tv_usec, &up->tv_usec);
 439        }
 440        return err;
 441}
 442
 443struct ifmap32 {
 444        compat_ulong_t mem_start;
 445        compat_ulong_t mem_end;
 446        unsigned short base_addr;
 447        unsigned char irq;
 448        unsigned char dma;
 449        unsigned char port;
 450};
 451
 452struct ifreq32 {
 453#define IFHWADDRLEN     6
 454#define IFNAMSIZ        16
 455        union {
 456                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
 457        } ifr_ifrn;
 458        union {
 459                struct  sockaddr ifru_addr;
 460                struct  sockaddr ifru_dstaddr;
 461                struct  sockaddr ifru_broadaddr;
 462                struct  sockaddr ifru_netmask;
 463                struct  sockaddr ifru_hwaddr;
 464                short   ifru_flags;
 465                compat_int_t     ifru_ivalue;
 466                compat_int_t     ifru_mtu;
 467                struct  ifmap32 ifru_map;
 468                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
 469                char    ifru_newname[IFNAMSIZ];
 470                compat_caddr_t ifru_data;
 471            /* XXXX? ifru_settings should be here */
 472        } ifr_ifru;
 473};
 474
 475struct ifconf32 {
 476        compat_int_t    ifc_len;                        /* size of buffer       */
 477        compat_caddr_t  ifcbuf;
 478};
 479
 480static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
 481{
 482        struct net_device *dev;
 483        struct ifreq32 ifr32;
 484        int err;
 485
 486        if (copy_from_user(&ifr32, compat_ptr(arg), sizeof(ifr32)))
 487                return -EFAULT;
 488
 489        dev = dev_get_by_index(ifr32.ifr_ifindex);
 490        if (!dev)
 491                return -ENODEV;
 492
 493        strlcpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name));
 494        dev_put(dev);
 495        
 496        err = copy_to_user(compat_ptr(arg), &ifr32, sizeof(ifr32));
 497        return (err ? -EFAULT : 0);
 498}
 499
 500static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
 501{
 502        struct ifconf32 ifc32;
 503        struct ifconf ifc;
 504        struct ifconf __user *uifc;
 505        struct ifreq32 __user *ifr32;
 506        struct ifreq __user *ifr;
 507        unsigned int i, j;
 508        int err;
 509
 510        if (copy_from_user(&ifc32, compat_ptr(arg), sizeof(struct ifconf32)))
 511                return -EFAULT;
 512
 513        if (ifc32.ifcbuf == 0) {
 514                ifc32.ifc_len = 0;
 515                ifc.ifc_len = 0;
 516                ifc.ifc_req = NULL;
 517                uifc = compat_alloc_user_space(sizeof(struct ifconf));
 518        } else {
 519                size_t len =((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) *
 520                        sizeof (struct ifreq);
 521                uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
 522                ifc.ifc_len = len;
 523                ifr = ifc.ifc_req = (void __user *)(uifc + 1);
 524                ifr32 = compat_ptr(ifc32.ifcbuf);
 525                for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) {
 526                        if (copy_in_user(ifr, ifr32, sizeof(struct ifreq32)))
 527                                return -EFAULT;
 528                        ifr++;
 529                        ifr32++; 
 530                }
 531        }
 532        if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
 533                return -EFAULT;
 534
 535        err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)uifc); 
 536        if (err)
 537                return err;
 538
 539        if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) 
 540                return -EFAULT;
 541
 542        ifr = ifc.ifc_req;
 543        ifr32 = compat_ptr(ifc32.ifcbuf);
 544        for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len;
 545             i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) {
 546                if (copy_in_user(ifr32, ifr, sizeof (struct ifreq32)))
 547                        return -EFAULT;
 548                ifr32++;
 549                ifr++;
 550        }
 551
 552        if (ifc32.ifcbuf == 0) {
 553                /* Translate from 64-bit structure multiple to
 554                 * a 32-bit one.
 555                 */
 556                i = ifc.ifc_len;
 557                i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32));
 558                ifc32.ifc_len = i;
 559        } else {
 560                if (i <= ifc32.ifc_len)
 561                        ifc32.ifc_len = i;
 562                else
 563                        ifc32.ifc_len = i - sizeof (struct ifreq32);
 564        }
 565        if (copy_to_user(compat_ptr(arg), &ifc32, sizeof(struct ifconf32)))
 566                return -EFAULT;
 567
 568        return 0;
 569}
 570
 571static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 572{
 573        struct ifreq __user *ifr;
 574        struct ifreq32 __user *ifr32;
 575        u32 data;
 576        void __user *datap;
 577        
 578        ifr = compat_alloc_user_space(sizeof(*ifr));
 579        ifr32 = compat_ptr(arg);
 580
 581        if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
 582                return -EFAULT;
 583
 584        if (get_user(data, &ifr32->ifr_ifru.ifru_data))
 585                return -EFAULT;
 586
 587        datap = compat_ptr(data);
 588        if (put_user(datap, &ifr->ifr_ifru.ifru_data))
 589                return -EFAULT;
 590
 591        return sys_ioctl(fd, cmd, (unsigned long) ifr);
 592}
 593
 594static int bond_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 595{
 596        struct ifreq kifr;
 597        struct ifreq __user *uifr;
 598        struct ifreq32 __user *ifr32 = compat_ptr(arg);
 599        mm_segment_t old_fs;
 600        int err;
 601        u32 data;
 602        void __user *datap;
 603
 604        switch (cmd) {
 605        case SIOCBONDENSLAVE:
 606        case SIOCBONDRELEASE:
 607        case SIOCBONDSETHWADDR:
 608        case SIOCBONDCHANGEACTIVE:
 609                if (copy_from_user(&kifr, ifr32, sizeof(struct ifreq32)))
 610                        return -EFAULT;
 611
 612                old_fs = get_fs();
 613                set_fs (KERNEL_DS);
 614                err = sys_ioctl (fd, cmd, (unsigned long)&kifr);
 615                set_fs (old_fs);
 616
 617                return err;
 618        case SIOCBONDSLAVEINFOQUERY:
 619        case SIOCBONDINFOQUERY:
 620                uifr = compat_alloc_user_space(sizeof(*uifr));
 621                if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
 622                        return -EFAULT;
 623
 624                if (get_user(data, &ifr32->ifr_ifru.ifru_data))
 625                        return -EFAULT;
 626
 627                datap = compat_ptr(data);
 628                if (put_user(datap, &uifr->ifr_ifru.ifru_data))
 629                        return -EFAULT;
 630
 631                return sys_ioctl (fd, cmd, (unsigned long)uifr);
 632        default:
 633                return -EINVAL;
 634        };
 635}
 636
 637int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 638{
 639        struct ifreq __user *u_ifreq64;
 640        struct ifreq32 __user *u_ifreq32 = compat_ptr(arg);
 641        char tmp_buf[IFNAMSIZ];
 642        void __user *data64;
 643        u32 data32;
 644
 645        if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
 646                           IFNAMSIZ))
 647                return -EFAULT;
 648        if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
 649                return -EFAULT;
 650        data64 = compat_ptr(data32);
 651
 652        u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
 653
 654        /* Don't check these user accesses, just let that get trapped
 655         * in the ioctl handler instead.
 656         */
 657        copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ);
 658        __put_user(data64, &u_ifreq64->ifr_ifru.ifru_data);
 659
 660        return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64);
 661}
 662
 663static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
 664{
 665        struct ifreq ifr;
 666        struct ifreq32 __user *uifr32;
 667        struct ifmap32 __user *uifmap32;
 668        mm_segment_t old_fs;
 669        int err;
 670        
 671        uifr32 = compat_ptr(arg);
 672        uifmap32 = &uifr32->ifr_ifru.ifru_map;
 673        switch (cmd) {
 674        case SIOCSIFMAP:
 675                err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
 676                err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
 677                err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
 678                err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
 679                err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
 680                err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
 681                err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
 682                if (err)
 683                        return -EFAULT;
 684                break;
 685        default:
 686                if (copy_from_user(&ifr, uifr32, sizeof(*uifr32)))
 687                        return -EFAULT;
 688                break;
 689        }
 690        old_fs = get_fs();
 691        set_fs (KERNEL_DS);
 692        err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
 693        set_fs (old_fs);
 694        if (!err) {
 695                switch (cmd) {
 696                case SIOCGIFFLAGS:
 697                case SIOCGIFMETRIC:
 698                case SIOCGIFMTU:
 699                case SIOCGIFMEM:
 700                case SIOCGIFHWADDR:
 701                case SIOCGIFINDEX:
 702                case SIOCGIFADDR:
 703                case SIOCGIFBRDADDR:
 704                case SIOCGIFDSTADDR:
 705                case SIOCGIFNETMASK:
 706                case SIOCGIFTXQLEN:
 707                        if (copy_to_user(uifr32, &ifr, sizeof(*uifr32)))
 708                                return -EFAULT;
 709                        break;
 710                case SIOCGIFMAP:
 711                        err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
 712                        err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
 713                        err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
 714                        err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
 715                        err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
 716                        err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
 717                        err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
 718                        if (err)
 719                                err = -EFAULT;
 720                        break;
 721                }
 722        }
 723        return err;
 724}
 725
 726struct rtentry32 {
 727        u32             rt_pad1;
 728        struct sockaddr rt_dst;         /* target address               */
 729        struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
 730        struct sockaddr rt_genmask;     /* target network mask (IP)     */
 731        unsigned short  rt_flags;
 732        short           rt_pad2;
 733        u32             rt_pad3;
 734        unsigned char   rt_tos;
 735        unsigned char   rt_class;
 736        short           rt_pad4;
 737        short           rt_metric;      /* +1 for binary compatibility! */
 738        /* char * */ u32 rt_dev;        /* forcing the device at add    */
 739        u32             rt_mtu;         /* per route MTU/Window         */
 740        u32             rt_window;      /* Window clamping              */
 741        unsigned short  rt_irtt;        /* Initial RTT                  */
 742
 743};
 744
 745struct in6_rtmsg32 {
 746        struct in6_addr         rtmsg_dst;
 747        struct in6_addr         rtmsg_src;
 748        struct in6_addr         rtmsg_gateway;
 749        u32                     rtmsg_type;
 750        u16                     rtmsg_dst_len;
 751        u16                     rtmsg_src_len;
 752        u32                     rtmsg_metric;
 753        u32                     rtmsg_info;
 754        u32                     rtmsg_flags;
 755        s32                     rtmsg_ifindex;
 756};
 757
 758static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 759{
 760        int ret;
 761        void *r = NULL;
 762        struct in6_rtmsg r6;
 763        struct rtentry r4;
 764        char devname[16];
 765        u32 rtdev;
 766        mm_segment_t old_fs = get_fs();
 767        
 768        struct socket *mysock = sockfd_lookup(fd, &ret);
 769
 770        if (mysock && mysock->sk && mysock->sk->sk_family == AF_INET6) { /* ipv6 */
 771                struct in6_rtmsg32 __user *ur6 = compat_ptr(arg);
 772                ret = copy_from_user (&r6.rtmsg_dst, &(ur6->rtmsg_dst),
 773                        3 * sizeof(struct in6_addr));
 774                ret |= __get_user (r6.rtmsg_type, &(ur6->rtmsg_type));
 775                ret |= __get_user (r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
 776                ret |= __get_user (r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
 777                ret |= __get_user (r6.rtmsg_metric, &(ur6->rtmsg_metric));
 778                ret |= __get_user (r6.rtmsg_info, &(ur6->rtmsg_info));
 779                ret |= __get_user (r6.rtmsg_flags, &(ur6->rtmsg_flags));
 780                ret |= __get_user (r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
 781                
 782                r = (void *) &r6;
 783        } else { /* ipv4 */
 784                struct rtentry32 __user *ur4 = compat_ptr(arg);
 785                ret = copy_from_user (&r4.rt_dst, &(ur4->rt_dst),
 786                                        3 * sizeof(struct sockaddr));
 787                ret |= __get_user (r4.rt_flags, &(ur4->rt_flags));
 788                ret |= __get_user (r4.rt_metric, &(ur4->rt_metric));
 789                ret |= __get_user (r4.rt_mtu, &(ur4->rt_mtu));
 790                ret |= __get_user (r4.rt_window, &(ur4->rt_window));
 791                ret |= __get_user (r4.rt_irtt, &(ur4->rt_irtt));
 792                ret |= __get_user (rtdev, &(ur4->rt_dev));
 793                if (rtdev) {
 794                        ret |= copy_from_user (devname, compat_ptr(rtdev), 15);
 795                        r4.rt_dev = devname; devname[15] = 0;
 796                } else
 797                        r4.rt_dev = NULL;
 798
 799                r = (void *) &r4;
 800        }
 801
 802        if (ret) {
 803                ret = -EFAULT;
 804                goto out;
 805        }
 806
 807        set_fs (KERNEL_DS);
 808        ret = sys_ioctl (fd, cmd, (unsigned long) r);
 809        set_fs (old_fs);
 810
 811out:
 812        if (mysock)
 813                sockfd_put(mysock);
 814
 815        return ret;
 816}
 817#endif
 818
 819struct hd_geometry32 {
 820        unsigned char heads;
 821        unsigned char sectors;
 822        unsigned short cylinders;
 823        u32 start;
 824};
 825                        
 826static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
 827{
 828        mm_segment_t old_fs = get_fs();
 829        struct hd_geometry geo;
 830        struct hd_geometry32 __user *ugeo;
 831        int err;
 832        
 833        set_fs (KERNEL_DS);
 834        err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo);
 835        set_fs (old_fs);
 836        ugeo = compat_ptr(arg);
 837        if (!err) {
 838                err = copy_to_user (ugeo, &geo, 4);
 839                err |= __put_user (geo.start, &ugeo->start);
 840        }
 841        return err ? -EFAULT : 0;
 842}
 843
 844struct fb_fix_screeninfo32 {
 845        char                    id[16];
 846        compat_caddr_t  smem_start;
 847        u32                     smem_len;
 848        u32                     type;
 849        u32                     type_aux;
 850        u32                     visual;
 851        u16                     xpanstep;
 852        u16                     ypanstep;
 853        u16                     ywrapstep;
 854        u32                     line_length;
 855        compat_caddr_t  mmio_start;
 856        u32                     mmio_len;
 857        u32                     accel;
 858        u16                     reserved[3];
 859};
 860
 861struct fb_cmap32 {
 862        u32                     start;
 863        u32                     len;
 864        compat_caddr_t  red;
 865        compat_caddr_t  green;
 866        compat_caddr_t  blue;
 867        compat_caddr_t  transp;
 868};
 869
 870static int fb_getput_cmap(unsigned int fd, unsigned int cmd, unsigned long arg)
 871{
 872        struct fb_cmap_user __user *cmap;
 873        struct fb_cmap32 __user *cmap32;
 874        __u32 data;
 875        int err;
 876
 877        cmap = compat_alloc_user_space(sizeof(*cmap));
 878        cmap32 = compat_ptr(arg);
 879
 880        if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32)))
 881                return -EFAULT;
 882
 883        if (get_user(data, &cmap32->red) ||
 884            put_user(compat_ptr(data), &cmap->red) ||
 885            get_user(data, &cmap32->green) ||
 886            put_user(compat_ptr(data), &cmap->green) ||
 887            get_user(data, &cmap32->blue) ||
 888            put_user(compat_ptr(data), &cmap->blue) ||
 889            get_user(data, &cmap32->transp) ||
 890            put_user(compat_ptr(data), &cmap->transp))
 891                return -EFAULT;
 892
 893        err = sys_ioctl(fd, cmd, (unsigned long) cmap);
 894
 895        if (!err) {
 896                if (copy_in_user(&cmap32->start,
 897                                 &cmap->start,
 898                                 2 * sizeof(__u32)))
 899                        err = -EFAULT;
 900        }
 901        return err;
 902}
 903
 904static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
 905                                  struct fb_fix_screeninfo32 __user *fix32)
 906{
 907        __u32 data;
 908        int err;
 909
 910        err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id));
 911
 912        data = (__u32) (unsigned long) fix->smem_start;
 913        err |= put_user(data, &fix32->smem_start);
 914
 915        err |= put_user(fix->smem_len, &fix32->smem_len);
 916        err |= put_user(fix->type, &fix32->type);
 917        err |= put_user(fix->type_aux, &fix32->type_aux);
 918        err |= put_user(fix->visual, &fix32->visual);
 919        err |= put_user(fix->xpanstep, &fix32->xpanstep);
 920        err |= put_user(fix->ypanstep, &fix32->ypanstep);
 921        err |= put_user(fix->ywrapstep, &fix32->ywrapstep);
 922        err |= put_user(fix->line_length, &fix32->line_length);
 923
 924        data = (__u32) (unsigned long) fix->mmio_start;
 925        err |= put_user(data, &fix32->mmio_start);
 926
 927        err |= put_user(fix->mmio_len, &fix32->mmio_len);
 928        err |= put_user(fix->accel, &fix32->accel);
 929        err |= copy_to_user(fix32->reserved, fix->reserved,
 930                            sizeof(fix->reserved));
 931
 932        return err;
 933}
 934
 935static int fb_get_fscreeninfo(unsigned int fd, unsigned int cmd, unsigned long arg)
 936{
 937        mm_segment_t old_fs;
 938        struct fb_fix_screeninfo fix;
 939        struct fb_fix_screeninfo32 __user *fix32;
 940        int err;
 941
 942        fix32 = compat_ptr(arg);
 943
 944        old_fs = get_fs();
 945        set_fs(KERNEL_DS);
 946        err = sys_ioctl(fd, cmd, (unsigned long) &fix);
 947        set_fs(old_fs);
 948
 949        if (!err)
 950                err = do_fscreeninfo_to_user(&fix, fix32);
 951
 952        return err;
 953}
 954
 955static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 956{
 957        int err;
 958
 959        switch (cmd) {
 960        case FBIOGET_FSCREENINFO:
 961                err = fb_get_fscreeninfo(fd,cmd, arg);
 962                break;
 963
 964        case FBIOGETCMAP:
 965        case FBIOPUTCMAP:
 966                err = fb_getput_cmap(fd, cmd, arg);
 967                break;
 968
 969        default:
 970                do {
 971                        static int count;
 972                        if (++count <= 20)
 973                                printk("%s: Unknown fb ioctl cmd fd(%d) "
 974                                       "cmd(%08x) arg(%08lx)\n",
 975                                       __FUNCTION__, fd, cmd, arg);
 976                } while(0);
 977                err = -ENOSYS;
 978                break;
 979        };
 980
 981        return err;
 982}
 983
 984static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 985{
 986        mm_segment_t old_fs = get_fs();
 987        unsigned long kval;
 988        unsigned int __user *uvp;
 989        int error;
 990
 991        set_fs(KERNEL_DS);
 992        error = sys_ioctl(fd, cmd, (long)&kval);
 993        set_fs(old_fs);
 994
 995        if(error == 0) {
 996                uvp = compat_ptr(arg);
 997                if(put_user(kval, uvp))
 998                        error = -EFAULT;
 999        }
1000        return error;
1001}
1002
1003
1004typedef struct sg_io_hdr32 {
1005        compat_int_t interface_id;      /* [i] 'S' for SCSI generic (required) */
1006        compat_int_t dxfer_direction;   /* [i] data transfer direction  */
1007        unsigned char cmd_len;          /* [i] SCSI command length ( <= 16 bytes) */
1008        unsigned char mx_sb_len;                /* [i] max length to write to sbp */
1009        unsigned short iovec_count;     /* [i] 0 implies no scatter gather */
1010        compat_uint_t dxfer_len;                /* [i] byte count of data transfer */
1011        compat_uint_t dxferp;           /* [i], [*io] points to data transfer memory
1012                                              or scatter gather list */
1013        compat_uptr_t cmdp;             /* [i], [*i] points to command to perform */
1014        compat_uptr_t sbp;              /* [i], [*o] points to sense_buffer memory */
1015        compat_uint_t timeout;          /* [i] MAX_UINT->no timeout (unit: millisec) */
1016        compat_uint_t flags;            /* [i] 0 -> default, see SG_FLAG... */
1017        compat_int_t pack_id;           /* [i->o] unused internally (normally) */
1018        compat_uptr_t usr_ptr;          /* [i->o] unused internally */
1019        unsigned char status;           /* [o] scsi status */
1020        unsigned char masked_status;    /* [o] shifted, masked scsi status */
1021        unsigned char msg_status;               /* [o] messaging level data (optional) */
1022        unsigned char sb_len_wr;                /* [o] byte count actually written to sbp */
1023        unsigned short host_status;     /* [o] errors from host adapter */
1024        unsigned short driver_status;   /* [o] errors from software driver */
1025        compat_int_t resid;             /* [o] dxfer_len - actual_transferred */
1026        compat_uint_t duration;         /* [o] time taken by cmd (unit: millisec) */
1027        compat_uint_t info;             /* [o] auxiliary information */
1028} sg_io_hdr32_t;  /* 64 bytes long (on sparc32) */
1029
1030typedef struct sg_iovec32 {
1031        compat_uint_t iov_base;
1032        compat_uint_t iov_len;
1033} sg_iovec32_t;
1034
1035static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iovec_count)
1036{
1037        sg_iovec_t __user *iov = (sg_iovec_t __user *) (sgio + 1);
1038        sg_iovec32_t __user *iov32 = dxferp;
1039        int i;
1040
1041        for (i = 0; i < iovec_count; i++) {
1042                u32 base, len;
1043
1044                if (get_user(base, &iov32[i].iov_base) ||
1045                    get_user(len, &iov32[i].iov_len) ||
1046                    put_user(compat_ptr(base), &iov[i].iov_base) ||
1047                    put_user(len, &iov[i].iov_len))
1048                        return -EFAULT;
1049        }
1050
1051        if (put_user(iov, &sgio->dxferp))
1052                return -EFAULT;
1053        return 0;
1054}
1055
1056static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
1057{
1058        sg_io_hdr_t __user *sgio;
1059        sg_io_hdr32_t __user *sgio32;
1060        u16 iovec_count;
1061        u32 data;
1062        void __user *dxferp;
1063        int err;
1064
1065        sgio32 = compat_ptr(arg);
1066        if (get_user(iovec_count, &sgio32->iovec_count))
1067                return -EFAULT;
1068
1069        {
1070                void __user *top = compat_alloc_user_space(0);
1071                void __user *new = compat_alloc_user_space(sizeof(sg_io_hdr_t) +
1072                                       (iovec_count * sizeof(sg_iovec_t)));
1073                if (new > top)
1074                        return -EINVAL;
1075
1076                sgio = new;
1077        }
1078
1079        /* Ok, now construct.  */
1080        if (copy_in_user(&sgio->interface_id, &sgio32->interface_id,
1081                         (2 * sizeof(int)) +
1082                         (2 * sizeof(unsigned char)) +
1083                         (1 * sizeof(unsigned short)) +
1084                         (1 * sizeof(unsigned int))))
1085                return -EFAULT;
1086
1087        if (get_user(data, &sgio32->dxferp))
1088                return -EFAULT;
1089        dxferp = compat_ptr(data);
1090        if (iovec_count) {
1091                if (sg_build_iovec(sgio, dxferp, iovec_count))
1092                        return -EFAULT;
1093        } else {
1094                if (put_user(dxferp, &sgio->dxferp))
1095                        return -EFAULT;
1096        }
1097
1098        {
1099                unsigned char __user *cmdp;
1100                unsigned char __user *sbp;
1101
1102                if (get_user(data, &sgio32->cmdp))
1103                        return -EFAULT;
1104                cmdp = compat_ptr(data);
1105
1106                if (get_user(data, &sgio32->sbp))
1107                        return -EFAULT;
1108                sbp = compat_ptr(data);
1109
1110                if (put_user(cmdp, &sgio->cmdp) ||
1111                    put_user(sbp, &sgio->sbp))
1112                        return -EFAULT;
1113        }
1114
1115        if (copy_in_user(&sgio->timeout, &sgio32->timeout,
1116                         3 * sizeof(int)))
1117                return -EFAULT;
1118
1119        if (get_user(data, &sgio32->usr_ptr))
1120                return -EFAULT;
1121        if (put_user(compat_ptr(data), &sgio->usr_ptr))
1122                return -EFAULT;
1123
1124        if (copy_in_user(&sgio->status, &sgio32->status,
1125                         (4 * sizeof(unsigned char)) +
1126                         (2 * sizeof(unsigned (short))) +
1127                         (3 * sizeof(int))))
1128                return -EFAULT;
1129
1130        err = sys_ioctl(fd, cmd, (unsigned long) sgio);
1131
1132        if (err >= 0) {
1133                void __user *datap;
1134
1135                if (copy_in_user(&sgio32->pack_id, &sgio->pack_id,
1136                                 sizeof(int)) ||
1137                    get_user(datap, &sgio->usr_ptr) ||
1138                    put_user((u32)(unsigned long)datap,
1139                             &sgio32->usr_ptr) ||
1140                    copy_in_user(&sgio32->status, &sgio->status,
1141                                 (4 * sizeof(unsigned char)) +
1142                                 (2 * sizeof(unsigned short)) +
1143                                 (3 * sizeof(int))))
1144                        err = -EFAULT;
1145        }
1146
1147        return err;
1148}
1149
1150struct sock_fprog32 {
1151        unsigned short  len;
1152        compat_caddr_t  filter;
1153};
1154
1155#define PPPIOCSPASS32   _IOW('t', 71, struct sock_fprog32)
1156#define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32)
1157
1158static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
1159{
1160        struct sock_fprog32 __user *u_fprog32 = compat_ptr(arg);
1161        struct sock_fprog __user *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
1162        void __user *fptr64;
1163        u32 fptr32;
1164        u16 flen;
1165
1166        if (get_user(flen, &u_fprog32->len) ||
1167            get_user(fptr32, &u_fprog32->filter))
1168                return -EFAULT;
1169
1170        fptr64 = compat_ptr(fptr32);
1171
1172        if (put_user(flen, &u_fprog64->len) ||
1173            put_user(fptr64, &u_fprog64->filter))
1174                return -EFAULT;
1175
1176        if (cmd == PPPIOCSPASS32)
1177                cmd = PPPIOCSPASS;
1178        else
1179                cmd = PPPIOCSACTIVE;
1180
1181        return sys_ioctl(fd, cmd, (unsigned long) u_fprog64);
1182}
1183
1184struct ppp_option_data32 {
1185        compat_caddr_t  ptr;
1186        u32                     length;
1187        compat_int_t            transmit;
1188};
1189#define PPPIOCSCOMPRESS32       _IOW('t', 77, struct ppp_option_data32)
1190
1191struct ppp_idle32 {
1192        compat_time_t xmit_idle;
1193        compat_time_t recv_idle;
1194};
1195#define PPPIOCGIDLE32           _IOR('t', 63, struct ppp_idle32)
1196
1197static int ppp_gidle(unsigned int fd, unsigned int cmd, unsigned long arg)
1198{
1199        struct ppp_idle __user *idle;
1200        struct ppp_idle32 __user *idle32;
1201        __kernel_time_t xmit, recv;
1202        int err;
1203
1204        idle = compat_alloc_user_space(sizeof(*idle));
1205        idle32 = compat_ptr(arg);
1206
1207        err = sys_ioctl(fd, PPPIOCGIDLE, (unsigned long) idle);
1208
1209        if (!err) {
1210                if (get_user(xmit, &idle->xmit_idle) ||
1211                    get_user(recv, &idle->recv_idle) ||
1212                    put_user(xmit, &idle32->xmit_idle) ||
1213                    put_user(recv, &idle32->recv_idle))
1214                        err = -EFAULT;
1215        }
1216        return err;
1217}
1218
1219static int ppp_scompress(unsigned int fd, unsigned int cmd, unsigned long arg)
1220{
1221        struct ppp_option_data __user *odata;
1222        struct ppp_option_data32 __user *odata32;
1223        __u32 data;
1224        void __user *datap;
1225
1226        odata = compat_alloc_user_space(sizeof(*odata));
1227        odata32 = compat_ptr(arg);
1228
1229        if (get_user(data, &odata32->ptr))
1230                return -EFAULT;
1231
1232        datap = compat_ptr(data);
1233        if (put_user(datap, &odata->ptr))
1234                return -EFAULT;
1235
1236        if (copy_in_user(&odata->length, &odata32->length,
1237                         sizeof(__u32) + sizeof(int)))
1238                return -EFAULT;
1239
1240        return sys_ioctl(fd, PPPIOCSCOMPRESS, (unsigned long) odata);
1241}
1242
1243static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
1244{
1245        int err;
1246
1247        switch (cmd) {
1248        case PPPIOCGIDLE32:
1249                err = ppp_gidle(fd, cmd, arg);
1250                break;
1251
1252        case PPPIOCSCOMPRESS32:
1253                err = ppp_scompress(fd, cmd, arg);
1254                break;
1255
1256        default:
1257                do {
1258                        static int count;
1259                        if (++count <= 20)
1260                                printk("ppp_ioctl: Unknown cmd fd(%d) "
1261                                       "cmd(%08x) arg(%08x)\n",
1262                                       (int)fd, (unsigned int)cmd, (unsigned int)arg);
1263                } while(0);
1264                err = -EINVAL;
1265                break;
1266        };
1267
1268        return err;
1269}
1270
1271
1272struct mtget32 {
1273        compat_long_t   mt_type;
1274        compat_long_t   mt_resid;
1275        compat_long_t   mt_dsreg;
1276        compat_long_t   mt_gstat;
1277        compat_long_t   mt_erreg;
1278        compat_daddr_t  mt_fileno;
1279        compat_daddr_t  mt_blkno;
1280};
1281#define MTIOCGET32      _IOR('m', 2, struct mtget32)
1282
1283struct mtpos32 {
1284        compat_long_t   mt_blkno;
1285};
1286#define MTIOCPOS32      _IOR('m', 3, struct mtpos32)
1287
1288struct mtconfiginfo32 {
1289        compat_long_t   mt_type;
1290        compat_long_t   ifc_type;
1291        unsigned short  irqnr;
1292        unsigned short  dmanr;
1293        unsigned short  port;
1294        compat_ulong_t  debug;
1295        compat_uint_t   have_dens:1;
1296        compat_uint_t   have_bsf:1;
1297        compat_uint_t   have_fsr:1;
1298        compat_uint_t   have_bsr:1;
1299        compat_uint_t   have_eod:1;
1300        compat_uint_t   have_seek:1;
1301        compat_uint_t   have_tell:1;
1302        compat_uint_t   have_ras1:1;
1303        compat_uint_t   have_ras2:1;
1304        compat_uint_t   have_ras3:1;
1305        compat_uint_t   have_qfa:1;
1306        compat_uint_t   pad1:5;
1307        char    reserved[10];
1308};
1309#define MTIOCGETCONFIG32        _IOR('m', 4, struct mtconfiginfo32)
1310#define MTIOCSETCONFIG32        _IOW('m', 5, struct mtconfiginfo32)
1311
1312static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
1313{
1314        mm_segment_t old_fs = get_fs();
1315        struct mtconfiginfo info;
1316        struct mtconfiginfo32 __user *uinfo32;
1317        struct mtget get;
1318        struct mtget32 __user *umget32;
1319        struct mtpos pos;
1320        struct mtpos32 __user *upos32;
1321        unsigned long kcmd;
1322        void *karg;
1323        int err = 0;
1324
1325        switch(cmd) {
1326        case MTIOCPOS32:
1327                kcmd = MTIOCPOS;
1328                karg = &pos;
1329                break;
1330        case MTIOCGET32:
1331                kcmd = MTIOCGET;
1332                karg = &get;
1333                break;
1334        case MTIOCGETCONFIG32:
1335                kcmd = MTIOCGETCONFIG;
1336                karg = &info;
1337                break;
1338        case MTIOCSETCONFIG32:
1339                kcmd = MTIOCSETCONFIG;
1340                karg = &info;
1341                uinfo32 = compat_ptr(arg);
1342                err = __get_user(info.mt_type, &uinfo32->mt_type);
1343                err |= __get_user(info.ifc_type, &uinfo32->ifc_type);
1344                err |= __get_user(info.irqnr, &uinfo32->irqnr);
1345                err |= __get_user(info.dmanr, &uinfo32->dmanr);
1346                err |= __get_user(info.port, &uinfo32->port);
1347                err |= __get_user(info.debug, &uinfo32->debug);
1348                err |= __copy_from_user((char *)&info.debug
1349                                     + sizeof(info.debug),
1350                                     (char __user *)&uinfo32->debug
1351                                     + sizeof(uinfo32->debug), sizeof(__u32));
1352                if (err)
1353                        return -EFAULT;
1354                break;
1355        default:
1356                do {
1357                        static int count;
1358                        if (++count <= 20)
1359                                printk("mt_ioctl: Unknown cmd fd(%d) "
1360                                       "cmd(%08x) arg(%08x)\n",
1361                                       (int)fd, (unsigned int)cmd, (unsigned int)arg);
1362                } while(0);
1363                return -EINVAL;
1364        }
1365        set_fs (KERNEL_DS);
1366        err = sys_ioctl (fd, kcmd, (unsigned long)karg);
1367        set_fs (old_fs);
1368        if (err)
1369                return err;
1370        switch (cmd) {
1371        case MTIOCPOS32:
1372                upos32 = compat_ptr(arg);
1373                err = __put_user(pos.mt_blkno, &upos32->mt_blkno);
1374                break;
1375        case MTIOCGET32:
1376                umget32 = compat_ptr(arg);
1377                err = __put_user(get.mt_type, &umget32->mt_type);
1378                err |= __put_user(get.mt_resid, &umget32->mt_resid);
1379                err |= __put_user(get.mt_dsreg, &umget32->mt_dsreg);
1380                err |= __put_user(get.mt_gstat, &umget32->mt_gstat);
1381                err |= __put_user(get.mt_erreg, &umget32->mt_erreg);
1382                err |= __put_user(get.mt_fileno, &umget32->mt_fileno);
1383                err |= __put_user(get.mt_blkno, &umget32->mt_blkno);
1384                break;
1385        case MTIOCGETCONFIG32:
1386                uinfo32 = compat_ptr(arg);
1387                err = __put_user(info.mt_type, &uinfo32->mt_type);
1388                err |= __put_user(info.ifc_type, &uinfo32->ifc_type);
1389                err |= __put_user(info.irqnr, &uinfo32->irqnr);
1390                err |= __put_user(info.dmanr, &uinfo32->dmanr);
1391                err |= __put_user(info.port, &uinfo32->port);
1392                err |= __put_user(info.debug, &uinfo32->debug);
1393                err |= __copy_to_user((char __user *)&uinfo32->debug
1394                                           + sizeof(uinfo32->debug),
1395                                           (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
1396                break;
1397        case MTIOCSETCONFIG32:
1398                break;
1399        }
1400        return err ? -EFAULT: 0;
1401}
1402
1403struct cdrom_read_audio32 {
1404        union cdrom_addr        addr;
1405        u8                      addr_format;
1406        compat_int_t            nframes;
1407        compat_caddr_t          buf;
1408};
1409
1410struct cdrom_generic_command32 {
1411        unsigned char   cmd[CDROM_PACKET_SIZE];
1412        compat_caddr_t  buffer;
1413        compat_uint_t   buflen;
1414        compat_int_t    stat;
1415        compat_caddr_t  sense;
1416        unsigned char   data_direction;
1417        compat_int_t    quiet;
1418        compat_int_t    timeout;
1419        compat_caddr_t  reserved[1];
1420};
1421  
1422static int cdrom_do_read_audio(unsigned int fd, unsigned int cmd, unsigned long arg)
1423{
1424        struct cdrom_read_audio __user *cdread_audio;
1425        struct cdrom_read_audio32 __user *cdread_audio32;
1426        __u32 data;
1427        void __user *datap;
1428
1429        cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
1430        cdread_audio32 = compat_ptr(arg);
1431
1432        if (copy_in_user(&cdread_audio->addr,
1433                         &cdread_audio32->addr,
1434                         (sizeof(*cdread_audio32) -
1435                          sizeof(compat_caddr_t))))
1436                return -EFAULT;
1437
1438        if (get_user(data, &cdread_audio32->buf))
1439                return -EFAULT;
1440        datap = compat_ptr(data);
1441        if (put_user(datap, &cdread_audio->buf))
1442                return -EFAULT;
1443
1444        return sys_ioctl(fd, cmd, (unsigned long) cdread_audio);
1445}
1446
1447static int cdrom_do_generic_command(unsigned int fd, unsigned int cmd, unsigned long arg)
1448{
1449        struct cdrom_generic_command __user *cgc;
1450        struct cdrom_generic_command32 __user *cgc32;
1451        u32 data;
1452        unsigned char dir;
1453        int itmp;
1454
1455        cgc = compat_alloc_user_space(sizeof(*cgc));
1456        cgc32 = compat_ptr(arg);
1457
1458        if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
1459            get_user(data, &cgc32->buffer) ||
1460            put_user(compat_ptr(data), &cgc->buffer) ||
1461            copy_in_user(&cgc->buflen, &cgc32->buflen,
1462                         (sizeof(unsigned int) + sizeof(int))) ||
1463            get_user(data, &cgc32->sense) ||
1464            put_user(compat_ptr(data), &cgc->sense) ||
1465            get_user(dir, &cgc32->data_direction) ||
1466            put_user(dir, &cgc->data_direction) ||
1467            get_user(itmp, &cgc32->quiet) ||
1468            put_user(itmp, &cgc->quiet) ||
1469            get_user(itmp, &cgc32->timeout) ||
1470            put_user(itmp, &cgc->timeout) ||
1471            get_user(data, &cgc32->reserved[0]) ||
1472            put_user(compat_ptr(data), &cgc->reserved[0]))
1473                return -EFAULT;
1474
1475        return sys_ioctl(fd, cmd, (unsigned long) cgc);
1476}
1477
1478static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
1479{
1480        int err;
1481
1482        switch(cmd) {
1483        case CDROMREADAUDIO:
1484                err = cdrom_do_read_audio(fd, cmd, arg);
1485                break;
1486
1487        case CDROM_SEND_PACKET:
1488                err = cdrom_do_generic_command(fd, cmd, arg);
1489                break;
1490
1491        default:
1492                do {
1493                        static int count;
1494                        if (++count <= 20)
1495                                printk("cdrom_ioctl: Unknown cmd fd(%d) "
1496                                       "cmd(%08x) arg(%08x)\n",
1497                                       (int)fd, (unsigned int)cmd, (unsigned int)arg);
1498                } while(0);
1499                err = -EINVAL;
1500                break;
1501        };
1502
1503        return err;
1504}
1505
1506struct loop_info32 {
1507        compat_int_t    lo_number;      /* ioctl r/o */
1508        compat_dev_t    lo_device;      /* ioctl r/o */
1509        compat_ulong_t  lo_inode;       /* ioctl r/o */
1510        compat_dev_t    lo_rdevice;     /* ioctl r/o */
1511        compat_int_t    lo_offset;
1512        compat_int_t    lo_encrypt_type;
1513        compat_int_t    lo_encrypt_key_size;    /* ioctl w/o */
1514        compat_int_t    lo_flags;       /* ioctl r/o */
1515        char            lo_name[LO_NAME_SIZE];
1516        unsigned char   lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
1517        compat_ulong_t  lo_init[2];
1518        char            reserved[4];
1519};
1520
1521static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg)
1522{
1523        mm_segment_t old_fs = get_fs();
1524        struct loop_info l;
1525        struct loop_info32 __user *ul;
1526        int err = -EINVAL;
1527
1528        ul = compat_ptr(arg);
1529        switch(cmd) {
1530        case LOOP_SET_STATUS:
1531                err = get_user(l.lo_number, &ul->lo_number);
1532                err |= __get_user(l.lo_device, &ul->lo_device);
1533                err |= __get_user(l.lo_inode, &ul->lo_inode);
1534                err |= __get_user(l.lo_rdevice, &ul->lo_rdevice);
1535                err |= __copy_from_user(&l.lo_offset, &ul->lo_offset,
1536                        8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
1537                if (err) {
1538                        err = -EFAULT;
1539                } else {
1540                        set_fs (KERNEL_DS);
1541                        err = sys_ioctl (fd, cmd, (unsigned long)&l);
1542                        set_fs (old_fs);
1543                }
1544                break;
1545        case LOOP_GET_STATUS:
1546                set_fs (KERNEL_DS);
1547                err = sys_ioctl (fd, cmd, (unsigned long)&l);
1548                set_fs (old_fs);
1549                if (!err) {
1550                        err = put_user(l.lo_number, &ul->lo_number);
1551                        err |= __put_user(l.lo_device, &ul->lo_device);
1552                        err |= __put_user(l.lo_inode, &ul->lo_inode);
1553                        err |= __put_user(l.lo_rdevice, &ul->lo_rdevice);
1554                        err |= __copy_to_user(&ul->lo_offset, &l.lo_offset,
1555                                (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
1556                        if (err)
1557                                err = -EFAULT;
1558                }
1559                break;
1560        default: {
1561                static int count;
1562                if (++count <= 20)
1563                        printk("%s: Unknown loop ioctl cmd, fd(%d) "
1564                               "cmd(%08x) arg(%08lx)\n",
1565                               __FUNCTION__, fd, cmd, arg);
1566        }
1567        }
1568        return err;
1569}
1570
1571extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
1572
1573#ifdef CONFIG_VT
1574
1575static int vt_check(struct file *file)
1576{
1577        struct tty_struct *tty;
1578        struct inode *inode = file->f_dentry->d_inode;
1579        
1580        if (file->f_op->ioctl != tty_ioctl)
1581                return -EINVAL;
1582                        
1583        tty = (struct tty_struct *)file->private_data;
1584        if (tty_paranoia_check(tty, inode, "tty_ioctl"))
1585                return -EINVAL;
1586                                                        
1587        if (tty->driver->ioctl != vt_ioctl)
1588                return -EINVAL;
1589        
1590        /*
1591         * To have permissions to do most of the vt ioctls, we either have
1592         * to be the owner of the tty, or super-user.
1593         */
1594        if (current->signal->tty == tty || capable(CAP_SYS_ADMIN))
1595                return 1;
1596        return 0;                                                    
1597}
1598
1599struct consolefontdesc32 {
1600        unsigned short charcount;       /* characters in font (256 or 512) */
1601        unsigned short charheight;      /* scan lines per character (1-32) */
1602        compat_caddr_t chardata;        /* font data in expanded form */
1603};
1604
1605static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
1606{
1607        struct consolefontdesc32 __user *user_cfd = compat_ptr(arg);
1608        struct console_font_op op;
1609        compat_caddr_t data;
1610        int i, perm;
1611
1612        perm = vt_check(file);
1613        if (perm < 0) return perm;
1614        
1615        switch (cmd) {
1616        case PIO_FONTX:
1617                if (!perm)
1618                        return -EPERM;
1619                op.op = KD_FONT_OP_SET;
1620                op.flags = 0;
1621                op.width = 8;
1622                if (get_user(op.height, &user_cfd->charheight) ||
1623                    get_user(op.charcount, &user_cfd->charcount) ||
1624                    get_user(data, &user_cfd->chardata))
1625                        return -EFAULT;
1626                op.data = compat_ptr(data);
1627                return con_font_op(fg_console, &op);
1628        case GIO_FONTX:
1629                op.op = KD_FONT_OP_GET;
1630                op.flags = 0;
1631                op.width = 8;
1632                if (get_user(op.height, &user_cfd->charheight) ||
1633                    get_user(op.charcount, &user_cfd->charcount) ||
1634                    get_user(data, &user_cfd->chardata))
1635                        return -EFAULT;
1636                if (!data)
1637                        return 0;
1638                op.data = compat_ptr(data);
1639                i = con_font_op(fg_console, &op);
1640                if (i)
1641                        return i;
1642                if (put_user(op.height, &user_cfd->charheight) ||
1643                    put_user(op.charcount, &user_cfd->charcount) ||
1644                    put_user((compat_caddr_t)(unsigned long)op.data,
1645                                &user_cfd->chardata))
1646                        return -EFAULT;
1647                return 0;
1648        }
1649        return -EINVAL;
1650}
1651
1652struct console_font_op32 {
1653        compat_uint_t op;        /* operation code KD_FONT_OP_* */
1654        compat_uint_t flags;     /* KD_FONT_FLAG_* */
1655        compat_uint_t width, height;     /* font size */
1656        compat_uint_t charcount;
1657        compat_caddr_t data;    /* font data with height fixed to 32 */
1658};
1659                                        
1660static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
1661{
1662        struct console_font_op op;
1663        struct console_font_op32 __user *fontop = compat_ptr(arg);
1664        int perm = vt_check(file), i;
1665        struct vt_struct *vt;
1666        
1667        if (perm < 0) return perm;
1668        
1669        if (copy_from_user(&op, fontop, sizeof(struct console_font_op32)))
1670                return -EFAULT;
1671        if (!perm && op.op != KD_FONT_OP_GET)
1672                return -EPERM;
1673        op.data = compat_ptr(((struct console_font_op32 *)&op)->data);
1674        op.flags |= KD_FONT_FLAG_OLD;
1675        vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data;
1676        i = con_font_op(vt->vc_num, &op);
1677        if (i) return i;
1678        ((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
1679        if (copy_to_user(fontop, &op, sizeof(struct console_font_op32)))
1680                return -EFAULT;
1681        return 0;
1682}
1683
1684struct unimapdesc32 {
1685        unsigned short entry_ct;
1686        compat_caddr_t entries;
1687};
1688
1689static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
1690{
1691        struct unimapdesc32 tmp;
1692        struct unimapdesc32 __user *user_ud = compat_ptr(arg);
1693        int perm = vt_check(file);
1694        
1695        if (perm < 0) return perm;
1696        if (copy_from_user(&tmp, user_ud, sizeof tmp))
1697                return -EFAULT;
1698        switch (cmd) {
1699        case PIO_UNIMAP:
1700                if (!perm) return -EPERM;
1701                return con_set_unimap(fg_console, tmp.entry_ct, compat_ptr(tmp.entries));
1702        case GIO_UNIMAP:
1703                return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
1704        }
1705        return 0;
1706}
1707
1708#endif /* CONFIG_VT */
1709
1710static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg)
1711{
1712        mm_segment_t old_fs = get_fs();
1713        __kernel_uid_t kuid;
1714        int err;
1715
1716        cmd = SMB_IOC_GETMOUNTUID;
1717
1718        set_fs(KERNEL_DS);
1719        err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
1720        set_fs(old_fs);
1721
1722        if (err >= 0)
1723                err = put_user(kuid, (compat_uid_t __user *)compat_ptr(arg));
1724
1725        return err;
1726}
1727
1728struct atmif_sioc32 {
1729        compat_int_t    number;
1730        compat_int_t    length;
1731        compat_caddr_t  arg;
1732};
1733
1734struct atm_iobuf32 {
1735        compat_int_t    length;
1736        compat_caddr_t  buffer;
1737};
1738
1739#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
1740#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
1741#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
1742#define ATM_GETESI32      _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
1743#define ATM_GETADDR32     _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
1744#define ATM_RSTADDR32     _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32)
1745#define ATM_ADDADDR32     _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32)
1746#define ATM_DELADDR32     _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32)
1747#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32)
1748#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32)
1749#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32)
1750#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32)
1751#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32)
1752#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
1753#define ATM_GETLOOP32     _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
1754#define ATM_SETLOOP32     _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
1755#define ATM_QUERYLOOP32   _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
1756
1757static struct {
1758        unsigned int cmd32;
1759        unsigned int cmd;
1760} atm_ioctl_map[] = {
1761        { ATM_GETLINKRATE32, ATM_GETLINKRATE },
1762        { ATM_GETNAMES32,    ATM_GETNAMES },
1763        { ATM_GETTYPE32,     ATM_GETTYPE },
1764        { ATM_GETESI32,      ATM_GETESI },
1765        { ATM_GETADDR32,     ATM_GETADDR },
1766        { ATM_RSTADDR32,     ATM_RSTADDR },
1767        { ATM_ADDADDR32,     ATM_ADDADDR },
1768        { ATM_DELADDR32,     ATM_DELADDR },
1769        { ATM_GETCIRANGE32,  ATM_GETCIRANGE },
1770        { ATM_SETCIRANGE32,  ATM_SETCIRANGE },
1771        { ATM_SETESI32,      ATM_SETESI },
1772        { ATM_SETESIF32,     ATM_SETESIF },
1773        { ATM_GETSTAT32,     ATM_GETSTAT },
1774        { ATM_GETSTATZ32,    ATM_GETSTATZ },
1775        { ATM_GETLOOP32,     ATM_GETLOOP },
1776        { ATM_SETLOOP32,     ATM_SETLOOP },
1777        { ATM_QUERYLOOP32,   ATM_QUERYLOOP }
1778};
1779
1780#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0]))
1781
1782
1783static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
1784{
1785        struct atm_iobuf   __user *iobuf;
1786        struct atm_iobuf32 __user *iobuf32;
1787        u32 data;
1788        void __user *datap;
1789        int len, err;
1790
1791        iobuf = compat_alloc_user_space(sizeof(*iobuf));
1792        iobuf32 = compat_ptr(arg);
1793
1794        if (get_user(len, &iobuf32->length) ||
1795            get_user(data, &iobuf32->buffer))
1796                return -EFAULT;
1797        datap = compat_ptr(data);
1798        if (put_user(len, &iobuf->length) ||
1799            put_user(datap, &iobuf->buffer))
1800                return -EFAULT;
1801
1802        err = sys_ioctl(fd, cmd, (unsigned long)iobuf);
1803
1804        if (!err) {
1805                if (copy_in_user(&iobuf32->length, &iobuf->length,
1806                                 sizeof(int)))
1807                        err = -EFAULT;
1808        }
1809
1810        return err;
1811}
1812
1813static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
1814{
1815        struct atmif_sioc   __user *sioc;
1816        struct atmif_sioc32 __user *sioc32;
1817        u32 data;
1818        void __user *datap;
1819        int err;
1820        
1821        sioc = compat_alloc_user_space(sizeof(*sioc));
1822        sioc32 = compat_ptr(arg);
1823
1824        if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) ||
1825            get_user(data, &sioc32->arg))
1826                return -EFAULT;
1827        datap = compat_ptr(data);
1828        if (put_user(datap, &sioc->arg))
1829                return -EFAULT;
1830
1831        err = sys_ioctl(fd, cmd, (unsigned long) sioc);
1832
1833        if (!err) {
1834                if (copy_in_user(&sioc32->length, &sioc->length,
1835                                 sizeof(int)))
1836                        err = -EFAULT;
1837        }
1838        return err;
1839}
1840
1841static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
1842{
1843        int i;
1844        unsigned int cmd = 0;
1845        
1846        switch (cmd32) {
1847        case SONET_GETSTAT:
1848        case SONET_GETSTATZ:
1849        case SONET_GETDIAG:
1850        case SONET_SETDIAG:
1851        case SONET_CLRDIAG:
1852        case SONET_SETFRAMING:
1853        case SONET_GETFRAMING:
1854        case SONET_GETFRSENSE:
1855                return do_atmif_sioc(fd, cmd32, arg);
1856        }
1857
1858        for (i = 0; i < NR_ATM_IOCTL; i++) {
1859                if (cmd32 == atm_ioctl_map[i].cmd32) {
1860                        cmd = atm_ioctl_map[i].cmd;
1861                        break;
1862                }
1863        }
1864        if (i == NR_ATM_IOCTL)
1865                return -EINVAL;
1866        
1867        switch (cmd) {
1868        case ATM_GETNAMES:
1869                return do_atm_iobuf(fd, cmd, arg);
1870            
1871        case ATM_GETLINKRATE:
1872        case ATM_GETTYPE:
1873        case ATM_GETESI:
1874        case ATM_GETADDR:
1875        case ATM_RSTADDR:
1876        case ATM_ADDADDR:
1877        case ATM_DELADDR:
1878        case ATM_GETCIRANGE:
1879        case ATM_SETCIRANGE:
1880        case ATM_SETESI:
1881        case ATM_SETESIF:
1882        case ATM_GETSTAT:
1883        case ATM_GETSTATZ:
1884        case ATM_GETLOOP:
1885        case ATM_SETLOOP:
1886        case ATM_QUERYLOOP:
1887                return do_atmif_sioc(fd, cmd, arg);
1888        }
1889
1890        return -EINVAL;
1891}
1892
1893static __attribute_used__ int 
1894ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
1895{
1896        return -EINVAL;
1897}
1898
1899static int do_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg)
1900{
1901        /* It's basically doing the same job as w_long except that we
1902         * need to return EFBIG on result overflow. */
1903        int err;
1904        unsigned long val = 0;
1905        unsigned long __user *arg64 = compat_alloc_user_space(sizeof(long));
1906        
1907        err = sys_ioctl(fd, cmd, (unsigned long) arg64);
1908        if (!err) 
1909                err = get_user(val, arg64);
1910        if (!err && val >= (1UL << 32))
1911                err = -EFBIG;
1912        if (!err && put_user(val, (u32 __user *)compat_ptr(arg)))
1913                err = -EFAULT;
1914        return err;
1915}
1916
1917static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg)
1918{
1919        /* The mkswap binary hard codes it to Intel value :-((( */
1920        return do_blkgetsize(fd, BLKGETSIZE, arg);
1921}
1922
1923struct blkpg_ioctl_arg32 {
1924        compat_int_t op;
1925        compat_int_t flags;
1926        compat_int_t datalen;
1927        compat_caddr_t data;
1928};
1929
1930static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
1931{
1932        struct blkpg_ioctl_arg32 __user *ua32 = compat_ptr(arg);
1933        struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
1934        compat_caddr_t udata;
1935        compat_int_t n;
1936        int err;
1937        
1938        err = get_user(n, &ua32->op);
1939        err |= put_user(n, &a->op);
1940        err |= get_user(n, &ua32->flags);
1941        err |= put_user(n, &a->flags);
1942        err |= get_user(n, &ua32->datalen);
1943        err |= put_user(n, &a->datalen);
1944        err |= get_user(udata, &ua32->data);
1945        err |= put_user(compat_ptr(udata), &a->data);
1946        if (err)
1947                return err;
1948
1949        return sys_ioctl(fd, cmd, (unsigned long)a);
1950}
1951
1952static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
1953{
1954        return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
1955}
1956
1957/* Fix sizeof(sizeof()) breakage */
1958#define BLKBSZGET_32   _IOR(0x12,112,int)
1959#define BLKBSZSET_32   _IOW(0x12,113,int)
1960#define BLKGETSIZE64_32        _IOR(0x12,114,int)
1961
1962static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg)
1963{
1964       return sys_ioctl(fd, BLKBSZGET, (unsigned long)compat_ptr(arg));
1965}
1966
1967static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg)
1968{
1969       return sys_ioctl(fd, BLKBSZSET, (unsigned long)compat_ptr(arg));
1970}
1971
1972static int do_blkgetsize64(unsigned int fd, unsigned int cmd,
1973                          unsigned long arg)
1974{
1975       return sys_ioctl(fd, BLKGETSIZE64, (unsigned long)compat_ptr(arg));
1976}
1977
1978/* Bluetooth ioctls */
1979#define HCIUARTSETPROTO _IOW('U', 200, int)
1980#define HCIUARTGETPROTO _IOR('U', 201, int)
1981
1982#define BNEPCONNADD     _IOW('B', 200, int)
1983#define BNEPCONNDEL     _IOW('B', 201, int)
1984#define BNEPGETCONNLIST _IOR('B', 210, int)
1985#define BNEPGETCONNINFO _IOR('B', 211, int)
1986
1987#define CMTPCONNADD     _IOW('C', 200, int)
1988#define CMTPCONNDEL     _IOW('C', 201, int)
1989#define CMTPGETCONNLIST _IOR('C', 210, int)
1990#define CMTPGETCONNINFO _IOR('C', 211, int)
1991
1992#define HIDPCONNADD     _IOW('H', 200, int)
1993#define HIDPCONNDEL     _IOW('H', 201, int)
1994#define HIDPGETCONNLIST _IOR('H', 210, int)
1995#define HIDPGETCONNINFO _IOR('H', 211, int)
1996
1997struct floppy_struct32 {
1998        compat_uint_t   size;
1999        compat_uint_t   sect;
2000        compat_uint_t   head;
2001        compat_uint_t   track;
2002        compat_uint_t   stretch;
2003        unsigned char   gap;
2004        unsigned char   rate;
2005        unsigned char   spec1;
2006        unsigned char   fmt_gap;
2007        const compat_caddr_t name;
2008};
2009
2010struct floppy_drive_params32 {
2011        char            cmos;
2012        compat_ulong_t  max_dtr;
2013        compat_ulong_t  hlt;
2014        compat_ulong_t  hut;
2015        compat_ulong_t  srt;
2016        compat_ulong_t  spinup;
2017        compat_ulong_t  spindown;
2018        unsigned char   spindown_offset;
2019        unsigned char   select_delay;
2020        unsigned char   rps;
2021        unsigned char   tracks;
2022        compat_ulong_t  timeout;
2023        unsigned char   interleave_sect;
2024        struct floppy_max_errors max_errors;
2025        char            flags;
2026        char            read_track;
2027        short           autodetect[8];
2028        compat_int_t    checkfreq;
2029        compat_int_t    native_format;
2030};
2031
2032struct floppy_drive_struct32 {
2033        signed char     flags;
2034        compat_ulong_t  spinup_date;
2035        compat_ulong_t  select_date;
2036        compat_ulong_t  first_read_date;
2037        short           probed_format;
2038        short           track;
2039        short           maxblock;
2040        short           maxtrack;
2041        compat_int_t    generation;
2042        compat_int_t    keep_data;
2043        compat_int_t    fd_ref;
2044        compat_int_t    fd_device;
2045        compat_int_t    last_checked;
2046        compat_caddr_t dmabuf;
2047        compat_int_t    bufblocks;
2048};
2049
2050struct floppy_fdc_state32 {
2051        compat_int_t    spec1;
2052        compat_int_t    spec2;
2053        compat_int_t    dtr;
2054        unsigned char   version;
2055        unsigned char   dor;
2056        compat_ulong_t  address;
2057        unsigned int    rawcmd:2;
2058        unsigned int    reset:1;
2059        unsigned int    need_configure:1;
2060        unsigned int    perp_mode:2;
2061        unsigned int    has_fifo:1;
2062        unsigned int    driver_version;
2063        unsigned char   track[4];
2064};
2065
2066struct floppy_write_errors32 {
2067        unsigned int    write_errors;
2068        compat_ulong_t  first_error_sector;
2069        compat_int_t    first_error_generation;
2070        compat_ulong_t  last_error_sector;
2071        compat_int_t    last_error_generation;
2072        compat_uint_t   badness;
2073};
2074
2075#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32)
2076#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32)
2077#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32)
2078#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32)
2079#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32)
2080#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32)
2081#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32)
2082#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32)
2083#define FDWERRORGET32  _IOR(2, 0x17, struct floppy_write_errors32)
2084
2085static struct {
2086        unsigned int    cmd32;
2087        unsigned int    cmd;
2088} fd_ioctl_trans_table[] = {
2089        { FDSETPRM32, FDSETPRM },
2090        { FDDEFPRM32, FDDEFPRM },
2091        { FDGETPRM32, FDGETPRM },
2092        { FDSETDRVPRM32, FDSETDRVPRM },
2093        { FDGETDRVPRM32, FDGETDRVPRM },
2094        { FDGETDRVSTAT32, FDGETDRVSTAT },
2095        { FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
2096        { FDGETFDCSTAT32, FDGETFDCSTAT },
2097        { FDWERRORGET32, FDWERRORGET }
2098};
2099
2100#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0]))
2101
2102static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
2103{
2104        mm_segment_t old_fs = get_fs();
2105        void *karg = NULL;
2106        unsigned int kcmd = 0;
2107        int i, err;
2108
2109        for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
2110                if (cmd == fd_ioctl_trans_table[i].cmd32) {
2111                        kcmd = fd_ioctl_trans_table[i].cmd;
2112                        break;
2113                }
2114        if (!kcmd)
2115                return -EINVAL;
2116
2117        switch (cmd) {
2118                case FDSETPRM32:
2119                case FDDEFPRM32:
2120                case FDGETPRM32:
2121                {
2122                        compat_uptr_t name;
2123                        struct floppy_struct32 __user *uf;
2124                        struct floppy_struct *f;
2125
2126                        uf = compat_ptr(arg);
2127                        f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
2128                        if (!karg)
2129                                return -ENOMEM;
2130                        if (cmd == FDGETPRM32)
2131                                break;
2132                        err = __get_user(f->size, &uf->size);
2133                        err |= __get_user(f->sect, &uf->sect);
2134                        err |= __get_user(f->head, &uf->head);
2135                        err |= __get_user(f->track, &uf->track);
2136                        err |= __get_user(f->stretch, &uf->stretch);
2137                        err |= __get_user(f->gap, &uf->gap);
2138                        err |= __get_user(f->rate, &uf->rate);
2139                        err |= __get_user(f->spec1, &uf->spec1);
2140                        err |= __get_user(f->fmt_gap, &uf->fmt_gap);
2141                        err |= __get_user(name, &uf->name);
2142                        f->name = compat_ptr(name);
2143                        if (err) {
2144                                err = -EFAULT;
2145                                goto out;
2146                        }
2147                        break;
2148                }
2149                case FDSETDRVPRM32:
2150                case FDGETDRVPRM32:
2151                {
2152                        struct floppy_drive_params32 __user *uf;
2153                        struct floppy_drive_params *f;
2154
2155                        uf = compat_ptr(arg);
2156                        f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
2157                        if (!karg)
2158                                return -ENOMEM;
2159                        if (cmd == FDGETDRVPRM32)
2160                                break;
2161                        err = __get_user(f->cmos, &uf->cmos);
2162                        err |= __get_user(f->max_dtr, &uf->max_dtr);
2163                        err |= __get_user(f->hlt, &uf->hlt);
2164                        err |= __get_user(f->hut, &uf->hut);
2165                        err |= __get_user(f->srt, &uf->srt);
2166                        err |= __get_user(f->spinup, &uf->spinup);
2167                        err |= __get_user(f->spindown, &uf->spindown);
2168                        err |= __get_user(f->spindown_offset, &uf->spindown_offset);
2169                        err |= __get_user(f->select_delay, &uf->select_delay);
2170                        err |= __get_user(f->rps, &uf->rps);
2171                        err |= __get_user(f->tracks, &uf->tracks);
2172                        err |= __get_user(f->timeout, &uf->timeout);
2173                        err |= __get_user(f->interleave_sect, &uf->interleave_sect);
2174                        err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors));
2175                        err |= __get_user(f->flags, &uf->flags);
2176                        err |= __get_user(f->read_track, &uf->read_track);
2177                        err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect));
2178                        err |= __get_user(f->checkfreq, &uf->checkfreq);
2179                        err |= __get_user(f->native_format, &uf->native_format);
2180                        if (err) {
2181                                err = -EFAULT;
2182                                goto out;
2183                        }
2184                        break;
2185                }
2186                case FDGETDRVSTAT32:
2187                case FDPOLLDRVSTAT32:
2188                        karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
2189                        if (!karg)
2190                                return -ENOMEM;
2191                        break;
2192                case FDGETFDCSTAT32:
2193                        karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
2194                        if (!karg)
2195                                return -ENOMEM;
2196                        break;
2197                case FDWERRORGET32:
2198                        karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
2199                        if (!karg)
2200                                return -ENOMEM;
2201                        break;
2202                default:
2203                        return -EINVAL;
2204        }
2205        set_fs (KERNEL_DS);
2206        err = sys_ioctl (fd, kcmd, (unsigned long)karg);
2207        set_fs (old_fs);
2208        if (err)
2209                goto out;
2210        switch (cmd) {
2211                case FDGETPRM32:
2212                {
2213                        struct floppy_struct *f = karg;
2214                        struct floppy_struct32 __user *uf = compat_ptr(arg);
2215
2216                        err = __put_user(f->size, &uf->size);
2217                        err |= __put_user(f->sect, &uf->sect);
2218                        err |= __put_user(f->head, &uf->head);
2219                        err |= __put_user(f->track, &uf->track);
2220                        err |= __put_user(f->stretch, &uf->stretch);
2221                        err |= __put_user(f->gap, &uf->gap);
2222                        err |= __put_user(f->rate, &uf->rate);
2223                        err |= __put_user(f->spec1, &uf->spec1);
2224                        err |= __put_user(f->fmt_gap, &uf->fmt_gap);
2225                        err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name);
2226                        break;
2227                }
2228                case FDGETDRVPRM32:
2229                {
2230                        struct floppy_drive_params32 __user *uf;
2231                        struct floppy_drive_params *f = karg;
2232
2233                        uf = compat_ptr(arg);
2234                        err = __put_user(f->cmos, &uf->cmos);
2235                        err |= __put_user(f->max_dtr, &uf->max_dtr);
2236                        err |= __put_user(f->hlt, &uf->hlt);
2237                        err |= __put_user(f->hut, &uf->hut);
2238                        err |= __put_user(f->srt, &uf->srt);
2239                        err |= __put_user(f->spinup, &uf->spinup);
2240                        err |= __put_user(f->spindown, &uf->spindown);
2241                        err |= __put_user(f->spindown_offset, &uf->spindown_offset);
2242                        err |= __put_user(f->select_delay, &uf->select_delay);
2243                        err |= __put_user(f->rps, &uf->rps);
2244                        err |= __put_user(f->tracks, &uf->tracks);
2245                        err |= __put_user(f->timeout, &uf->timeout);
2246                        err |= __put_user(f->interleave_sect, &uf->interleave_sect);
2247                        err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors));
2248                        err |= __put_user(f->flags, &uf->flags);
2249                        err |= __put_user(f->read_track, &uf->read_track);
2250                        err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect));
2251                        err |= __put_user(f->checkfreq, &uf->checkfreq);
2252                        err |= __put_user(f->native_format, &uf->native_format);
2253                        break;
2254                }
2255                case FDGETDRVSTAT32:
2256                case FDPOLLDRVSTAT32:
2257                {
2258                        struct floppy_drive_struct32 __user *uf;
2259                        struct floppy_drive_struct *f = karg;
2260
2261                        uf = compat_ptr(arg);
2262                        err = __put_user(f->flags, &uf->flags);
2263                        err |= __put_user(f->spinup_date, &uf->spinup_date);
2264                        err |= __put_user(f->select_date, &uf->select_date);
2265                        err |= __put_user(f->first_read_date, &uf->first_read_date);
2266                        err |= __put_user(f->probed_format, &uf->probed_format);
2267                        err |= __put_user(f->track, &uf->track);
2268                        err |= __put_user(f->maxblock, &uf->maxblock);
2269                        err |= __put_user(f->maxtrack, &uf->maxtrack);
2270                        err |= __put_user(f->generation, &uf->generation);
2271                        err |= __put_user(f->keep_data, &uf->keep_data);
2272                        err |= __put_user(f->fd_ref, &uf->fd_ref);
2273                        err |= __put_user(f->fd_device, &uf->fd_device);
2274                        err |= __put_user(f->last_checked, &uf->last_checked);
2275                        err |= __put_user((u64)f->dmabuf, &uf->dmabuf);
2276                        err |= __put_user((u64)f->bufblocks, &uf->bufblocks);
2277                        break;
2278                }
2279                case FDGETFDCSTAT32:
2280                {
2281                        struct floppy_fdc_state32 __user *uf;
2282                        struct floppy_fdc_state *f = karg;
2283
2284                        uf = compat_ptr(arg);
2285                        err = __put_user(f->spec1, &uf->spec1);
2286                        err |= __put_user(f->spec2, &uf->spec2);
2287                        err |= __put_user(f->dtr, &uf->dtr);
2288                        err |= __put_user(f->version, &uf->version);
2289                        err |= __put_user(f->dor, &uf->dor);
2290                        err |= __put_user(f->address, &uf->address);
2291                        err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address),
2292                                           (char *)&f->address + sizeof(f->address), sizeof(int));
2293                        err |= __put_user(f->driver_version, &uf->driver_version);
2294                        err |= __copy_to_user(uf->track, f->track, sizeof(f->track));
2295                        break;
2296                }
2297                case FDWERRORGET32:
2298                {
2299                        struct floppy_write_errors32 __user *uf;
2300                        struct floppy_write_errors *f = karg;
2301
2302                        uf = compat_ptr(arg);
2303                        err = __put_user(f->write_errors, &uf->write_errors);
2304                        err |= __put_user(f->first_error_sector, &uf->first_error_sector);
2305                        err |= __put_user(f->first_error_generation, &uf->first_error_generation);
2306                        err |= __put_user(f->last_error_sector, &uf->last_error_sector);
2307                        err |= __put_user(f->last_error_generation, &uf->last_error_generation);
2308                        err |= __put_user(f->badness, &uf->badness);
2309                        break;
2310                }
2311                default:
2312                        break;
2313        }
2314        if (err)
2315                err = -EFAULT;
2316
2317out:    if (karg) kfree(karg);
2318        return err;
2319}
2320
2321struct mtd_oob_buf32 {
2322        u_int32_t start;
2323        u_int32_t length;
2324        compat_caddr_t ptr;     /* unsigned char* */
2325};
2326
2327#define MEMWRITEOOB32   _IOWR('M',3,struct mtd_oob_buf32)
2328#define MEMREADOOB32    _IOWR('M',4,struct mtd_oob_buf32)
2329
2330static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
2331{
2332        struct mtd_oob_buf __user *buf = compat_alloc_user_space(sizeof(*buf));
2333        struct mtd_oob_buf32 __user *buf32 = compat_ptr(arg);
2334        u32 data;
2335        char __user *datap;
2336        unsigned int real_cmd;
2337        int err;
2338
2339        real_cmd = (cmd == MEMREADOOB32) ?
2340                MEMREADOOB : MEMWRITEOOB;
2341
2342        if (copy_in_user(&buf->start, &buf32->start,
2343                         2 * sizeof(u32)) ||
2344            get_user(data, &buf32->ptr))
2345                return -EFAULT;
2346        datap = compat_ptr(data);
2347        if (put_user(datap, &buf->ptr))
2348                return -EFAULT;
2349
2350        err = sys_ioctl(fd, real_cmd, (unsigned long) buf);
2351
2352        if (!err) {
2353                if (copy_in_user(&buf32->start, &buf->start,
2354                                 2 * sizeof(u32)))
2355                        err = -EFAULT;
2356        }
2357
2358        return err;
2359}       
2360
2361#define VFAT_IOCTL_READDIR_BOTH32       _IOR('r', 1, struct compat_dirent[2])
2362#define VFAT_IOCTL_READDIR_SHORT32      _IOR('r', 2, struct compat_dirent[2])
2363
2364static long
2365put_dirent32 (struct dirent *d, struct compat_dirent __user *d32)
2366{
2367        if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent[2])))
2368                return -EFAULT;
2369
2370        /* short name */
2371        __put_user(d->d_reclen, &d32->d_reclen);
2372        __put_user(0, d32->d_name + d->d_reclen);
2373        if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen))
2374                return -EFAULT;
2375<